ooxml-ui 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +40 -36
  2. package/custom-elements.json +211 -4
  3. package/dist/chrome/ruler.d.ts +60 -2
  4. package/dist/chrome/ruler.d.ts.map +1 -1
  5. package/dist/chrome/status-bar.d.ts +3 -1
  6. package/dist/chrome/status-bar.d.ts.map +1 -1
  7. package/dist/{chunk-T3HB5LMH.js → chunk-7FNDOWTX.js} +393 -15
  8. package/dist/{chunk-FLHM5Q4O.js → chunk-AYXFLBSV.js} +92 -13
  9. package/dist/{chunk-X7RINDJQ.js → chunk-JAJFLFAV.js} +1 -1
  10. package/dist/{chunk-OXKWNNNJ.js → chunk-VUB44CAJ.js} +1 -1
  11. package/dist/{chunk-JFJXBYRD.js → chunk-XNCWB2X6.js} +5 -0
  12. package/dist/{chunk-XDUYS4KK.js → chunk-Y2E22JVO.js} +1 -1
  13. package/dist/{chunk-ZV2Z4IWH.js → chunk-YK2DPYMU.js} +5 -2
  14. package/dist/{chunk-4QQASR5A.js → chunk-YP5S7DTT.js} +6 -5
  15. package/dist/comments/comments-pane.d.ts +116 -0
  16. package/dist/comments/comments-pane.d.ts.map +1 -0
  17. package/dist/comments/types.d.ts +80 -0
  18. package/dist/comments/types.d.ts.map +1 -0
  19. package/dist/controls.d.ts +4 -2
  20. package/dist/controls.d.ts.map +1 -1
  21. package/dist/controls.js +4 -4
  22. package/dist/docx/comments-panel.d.ts +8 -1
  23. package/dist/docx/image-media.d.ts +1 -1
  24. package/dist/docx/locales/en-ribbon.d.ts +1 -0
  25. package/dist/docx/locales/en.d.ts +1 -0
  26. package/dist/docx/localization-strings.d.ts +2 -1
  27. package/dist/docx/localization.d.ts +7 -1
  28. package/dist/docx/print-layout.d.ts +2 -2
  29. package/dist/docx/print-picture.d.ts +12 -0
  30. package/dist/docx/review-controller.d.ts +2 -0
  31. package/dist/docx/ruler.d.ts +7 -10
  32. package/dist/docx.js +289 -339
  33. package/dist/form/gradient-preset-gallery.d.ts +2 -2
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +8 -8
  36. package/dist/pptx/{chart-3d-view-scene-2KRQ5667.mjs → chart-3d-view-scene-6B5TOWB6.mjs} +3 -3
  37. package/dist/pptx/{chart-3d-view-scene-36DMZWZ3.cjs → chart-3d-view-scene-MJ6YNT56.cjs} +37 -37
  38. package/dist/pptx/{chunk-YOGDIDPB.mjs → chunk-AWKKC3VW.mjs} +8 -2
  39. package/dist/pptx/{chunk-XQZWZMGZ.cjs → chunk-SM3CWDIQ.cjs} +7 -17
  40. package/dist/pptx/{chunk-CJU4P5FT.cjs → chunk-STKGUT5S.cjs} +18 -12
  41. package/dist/pptx/{chunk-JSBGBVBH.mjs → chunk-VRFNAF3Q.mjs} +7 -17
  42. package/dist/pptx/{chunk-YHA6XAB3.cjs → chunk-XIQMFSNG.cjs} +1 -1
  43. package/dist/pptx/{chunk-YARCML7O.mjs → chunk-XQVKQD5Z.mjs} +294 -265
  44. package/dist/pptx/{chunk-XWE5GSE7.mjs → chunk-YI5LH5NN.mjs} +533 -428
  45. package/dist/pptx/{chunk-ADOC5JLI.mjs → chunk-YMTQLZ2I.mjs} +1 -1
  46. package/dist/pptx/{chunk-AIL3BNZS.cjs → chunk-YRHK45AB.cjs} +301 -265
  47. package/dist/pptx/{chunk-FEFQTZDM.cjs → chunk-ZK344LOB.cjs} +689 -574
  48. package/dist/pptx/dom/elements/chart.d.ts +2 -3
  49. package/dist/pptx/dom/elements/chart.d.ts.map +1 -1
  50. package/dist/pptx/dom/elements/table.d.ts.map +1 -1
  51. package/dist/pptx/dom/index.cjs +257 -246
  52. package/dist/pptx/dom/index.mjs +28 -17
  53. package/dist/pptx/export/html2canvas-clone.cjs +2 -2
  54. package/dist/pptx/export/html2canvas-clone.mjs +1 -1
  55. package/dist/pptx/i18n/index.cjs +6 -6
  56. package/dist/pptx/i18n/index.mjs +1 -1
  57. package/dist/pptx/i18n/translator.d.ts.map +1 -1
  58. package/dist/pptx/index.cjs +3035 -2991
  59. package/dist/pptx/index.mjs +5 -5
  60. package/dist/pptx/render/chart-axis-range.d.ts +7 -0
  61. package/dist/pptx/render/chart-axis-range.d.ts.map +1 -1
  62. package/dist/pptx/render/chart-axis-render.d.ts +3 -1
  63. package/dist/pptx/render/chart-axis-render.d.ts.map +1 -1
  64. package/dist/pptx/render/chart-axis-style.d.ts +5 -0
  65. package/dist/pptx/render/chart-axis-style.d.ts.map +1 -1
  66. package/dist/pptx/render/chart-axis.d.ts +1 -1
  67. package/dist/pptx/render/chart-axis.d.ts.map +1 -1
  68. package/dist/pptx/render/chart-cartesian-axes.d.ts.map +1 -1
  69. package/dist/pptx/render/chart-cartesian-bars.d.ts +3 -3
  70. package/dist/pptx/render/chart-cartesian-bars.d.ts.map +1 -1
  71. package/dist/pptx/render/chart-cartesian-percent-stacked.d.ts.map +1 -1
  72. package/dist/pptx/render/chart-cartesian.d.ts.map +1 -1
  73. package/dist/pptx/render/chart-combo-stock.cjs +3 -3
  74. package/dist/pptx/render/chart-combo-stock.mjs +1 -1
  75. package/dist/pptx/render/chart-combo.d.ts.map +1 -1
  76. package/dist/pptx/render/chart-gridlines-toggle.d.ts +13 -1
  77. package/dist/pptx/render/chart-gridlines-toggle.d.ts.map +1 -1
  78. package/dist/pptx/render/chart-helpers.d.ts +13 -13
  79. package/dist/pptx/render/chart-helpers.d.ts.map +1 -1
  80. package/dist/pptx/render/chart-horizontal-bars-helpers.d.ts +7 -3
  81. package/dist/pptx/render/chart-horizontal-bars-helpers.d.ts.map +1 -1
  82. package/dist/pptx/render/chart-horizontal-bars.d.ts.map +1 -1
  83. package/dist/pptx/render/chart-interaction-stacked.d.ts.map +1 -1
  84. package/dist/pptx/render/chart-overlays.cjs +7 -7
  85. package/dist/pptx/render/chart-overlays.mjs +1 -1
  86. package/dist/pptx/render/chart-palette.d.ts +5 -14
  87. package/dist/pptx/render/chart-palette.d.ts.map +1 -1
  88. package/dist/pptx/render/chart-quick-action-styles.d.ts +5 -3
  89. package/dist/pptx/render/chart-quick-action-styles.d.ts.map +1 -1
  90. package/dist/pptx/render/chart-scatter-x-axis.d.ts.map +1 -1
  91. package/dist/pptx/render/chart-style-palette.d.ts +52 -0
  92. package/dist/pptx/render/chart-style-palette.d.ts.map +1 -0
  93. package/dist/pptx/render/chart-surface-treemap.cjs +4 -4
  94. package/dist/pptx/render/chart-surface-treemap.mjs +1 -1
  95. package/dist/pptx/render/chart-view-model-bars.d.ts +31 -1
  96. package/dist/pptx/render/chart-view-model-bars.d.ts.map +1 -1
  97. package/dist/pptx/render/chart-view-model-build.d.ts.map +1 -1
  98. package/dist/pptx/render/chart-view-model.cjs +53 -41
  99. package/dist/pptx/render/chart-view-model.mjs +1 -1
  100. package/dist/pptx/render/chart-waterfall-map.cjs +6 -6
  101. package/dist/pptx/render/chart-waterfall-map.mjs +1 -1
  102. package/dist/pptx/render/connector-elbow-geometry.d.ts +7 -43
  103. package/dist/pptx/render/connector-elbow-geometry.d.ts.map +1 -1
  104. package/dist/pptx/render/foreign-object-svg-document.d.ts +12 -0
  105. package/dist/pptx/render/foreign-object-svg-document.d.ts.map +1 -1
  106. package/dist/pptx/render/index.d.ts +2 -0
  107. package/dist/pptx/render/index.d.ts.map +1 -1
  108. package/dist/pptx/render/table-cell-css.d.ts +3 -2
  109. package/dist/pptx/render/table-cell-css.d.ts.map +1 -1
  110. package/dist/pptx/render/table-cell-edit.d.ts +1 -1
  111. package/dist/pptx/render/table-cell-edit.d.ts.map +1 -1
  112. package/dist/pptx/render/table-cell-paragraphs.d.ts +29 -0
  113. package/dist/pptx/render/table-cell-paragraphs.d.ts.map +1 -0
  114. package/dist/pptx/render/table-style.d.ts +2 -0
  115. package/dist/pptx/render/table-style.d.ts.map +1 -1
  116. package/dist/pptx/render/title-bar.d.ts +5 -0
  117. package/dist/pptx/render/title-bar.d.ts.map +1 -1
  118. package/dist/pptx/render/viewer-root-options.d.ts +54 -0
  119. package/dist/pptx/render/viewer-root-options.d.ts.map +1 -0
  120. package/dist/pptx/web-components/office-token-bridge.d.ts.map +1 -1
  121. package/dist/pptx/web-components/registration-contract.d.ts.map +1 -1
  122. package/dist/presence.js +3 -3
  123. package/dist/registry.d.ts +2 -0
  124. package/dist/registry.d.ts.map +1 -1
  125. package/dist/ribbon/ribbon-tabs.d.ts +2 -1
  126. package/dist/ribbon/ribbon-tabs.d.ts.map +1 -1
  127. package/dist/smartart/smartart-svg.d.ts +3 -2
  128. package/dist/smartart.js +3 -3
  129. package/dist/suite/attachment-store.d.ts +13 -0
  130. package/dist/suite/document-store.d.ts +31 -0
  131. package/dist/suite/index.d.ts +2 -0
  132. package/dist/suite.js +132 -1
  133. package/dist/teams/app/channel-tab.d.ts +5 -0
  134. package/dist/teams/chat-composer.d.ts +3 -0
  135. package/dist/teams.js +6 -6
  136. package/dist/theme.js +2 -2
  137. package/dist/tokens.d.ts +5 -0
  138. package/dist/tokens.d.ts.map +1 -1
  139. package/dist/visio/styles/index.d.ts +2 -0
  140. package/dist/visio/styles/theme.d.ts +11 -0
  141. package/dist/visio/styles.d.ts +2 -2
  142. package/dist/visio.js +76 -25
  143. package/dist/xlsx/backstage/index.d.ts +4 -1
  144. package/dist/xlsx/backstage/pages-share.d.ts +19 -0
  145. package/dist/xlsx/backstage/parts.d.ts +3 -0
  146. package/dist/xlsx/chart-fill-binding.d.ts +2 -2
  147. package/dist/xlsx/chart-series-gradient-type.d.ts +3 -2
  148. package/dist/xlsx/collaboration-session.d.ts +9 -0
  149. package/dist/xlsx/collaboration-types.d.ts +41 -0
  150. package/dist/xlsx/collaboration.d.ts +56 -0
  151. package/dist/xlsx/component.d.ts +8 -0
  152. package/dist/xlsx/dialogs/comments-list.d.ts +4 -0
  153. package/dist/xlsx/dialogs/help-dialogs.d.ts +1 -1
  154. package/dist/xlsx/editor-core.d.ts +3 -0
  155. package/dist/xlsx/element-api.d.ts +19 -1
  156. package/dist/xlsx/events.d.ts +4 -1
  157. package/dist/xlsx/grid/remote-layer.d.ts +3 -0
  158. package/dist/xlsx/grid/sparkline.d.ts +3 -0
  159. package/dist/xlsx/grid/styles.d.ts +1 -1
  160. package/dist/xlsx/index.d.ts +1 -0
  161. package/dist/xlsx/ribbon-actions.d.ts +21 -0
  162. package/dist/xlsx/shell-commands.d.ts +1 -1
  163. package/dist/xlsx/title-bar.d.ts +4 -2
  164. package/dist/xlsx.js +712 -90
  165. package/package.json +3 -3
  166. package/dist/pptx/web-components/status-bar-styles.d.ts +0 -3
  167. package/dist/pptx/web-components/status-bar-styles.d.ts.map +0 -1
  168. package/dist/pptx/web-components/title-bar-styles.d.ts +0 -7
  169. package/dist/pptx/web-components/title-bar-styles.d.ts.map +0 -1
package/dist/visio.js CHANGED
@@ -1,8 +1,9 @@
1
- import { attachKeyTips, registerControls, readOfficeProfile, sanitizeOfficeProfile, writeOfficeProfile } from './chunk-T3HB5LMH.js';
1
+ import { themeBridge, installOfficeUiTheme } from './chunk-JAJFLFAV.js';
2
+ import { attachKeyTips, registerControls, readOfficeProfile, sanitizeOfficeProfile, writeOfficeProfile } from './chunk-7FNDOWTX.js';
2
3
  import { getIcon, registerIcon } from './chunk-BOX43CZD.js';
3
- import { definePresence } from './chunk-OXKWNNNJ.js';
4
- import './chunk-ZV2Z4IWH.js';
5
- import './chunk-JFJXBYRD.js';
4
+ import { definePresence } from './chunk-VUB44CAJ.js';
5
+ import './chunk-YK2DPYMU.js';
6
+ import './chunk-XNCWB2X6.js';
6
7
  import { FOREIGN_VECTOR_SCENE_LIMITS, EMPTY_TEXT_SEARCH, EMPTY_EDIT_STATE, assertViewableDocument, indexDocumentText, searchDocumentText, validateSearchQuery, MAX_INPUT_BYTES, DocumentHistory, snapshotEdits, ForeignVectorBudget, VISIO_IDENTITY_TRANSFORM, composeVisioTransform, compatibilityNotes, compatibilityText, visioGradientInstances, visioRenderedGradientStopCount, inspectForeignVectorResource, copySnapshotScene, editErrorMessage, eventKeys, propertyKeys, TEXT_SEARCH_LIMITS, isEditCancellation, visioPageInsertCommand, visioQuarterTurnCommand, visioLocalRotationShape, visioStraightLineHandles, visioPageEditToDrawing, textSearchStatus, visioRotationPreviewTransform, visioFillPatternTransform, visioRenderedGradientStops, visioStrokeGradient, visioNextShapeId } from 'ooxml-core/visio/ui';
7
8
  export { TEXT_SEARCH_LIMITS, compatibilityNotes, compatibilityText, demoDocument, eventKeys, propertyKeys } from 'ooxml-core/visio/ui';
8
9
  import { VISIO_VISIBILITY_LIMITS, loadVisio, getVisioPageLayers, resolveVisioPageVisibility, visioFilledArrow, layoutVisioFilledArrowLine, visioOpenArrowPath } from 'ooxml-core/visio';
@@ -886,10 +887,6 @@ function wireLayerControls(panel, controller) {
886
887
  // src/visio/styles.ts
887
888
  var viewerStyles = `
888
889
  :host {
889
- --_vv-bg:var(--vv-background,#eceae8); --_vv-surface:var(--vv-surface,#fff);
890
- --_vv-secondary:var(--vv-secondary,#f3f2f1); --_vv-ink:var(--vv-ink,#1f1f1f);
891
- --_vv-muted:var(--vv-muted,#605e5c); --_vv-border:var(--vv-border,#e1dfdd);
892
- --_vv-accent:var(--vv-accent,#3955a3); --_vv-accent-soft:var(--vv-accent-soft,rgba(57,85,163,.10));
893
890
  display:flex; flex-direction:column; min-width:0; min-height:320px; height:100%; overflow:hidden;
894
891
  color:var(--_vv-ink); background:var(--_vv-bg); font:12px/1.5 "Segoe UI",Arial,sans-serif; contain:layout;
895
892
  }
@@ -899,7 +896,7 @@ button,select,input,textarea { font:inherit; color:inherit; border:1px solid var
899
896
  button { cursor:pointer; }
900
897
  button:hover:enabled { background:var(--_vv-accent-soft); border-color:var(--_vv-accent); }
901
898
  button:disabled { opacity:.4; cursor:default; }
902
- button:focus-visible,select:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible { outline:2px solid var(--vv-focus,var(--_vv-accent)); outline-offset:2px; }
899
+ button:focus-visible,select:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible { outline:2px solid var(--_vv-focus); outline-offset:2px; }
903
900
  button[aria-pressed="true"] { color:var(--_vv-accent); background:var(--_vv-accent-soft); }
904
901
  .toolbar { flex:none; min-width:0; border-bottom:1px solid var(--_vv-border); background:var(--_vv-surface); }
905
902
  .spacer { flex:1; }
@@ -913,7 +910,7 @@ button[aria-pressed="true"] { color:var(--_vv-accent); background:var(--_vv-acce
913
910
  .pane-heading { height:37px; display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px 10px; border-bottom:1px solid var(--_vv-border); font-size:11px; font-weight:600; }
914
911
  .inspector-kind { color:var(--_vv-muted); font-size:10px; font-weight:400; }
915
912
  .viewport { position:relative; display:flex; flex-direction:column; flex:1; overflow:auto; min-width:0; min-height:0; padding:16px 4px; background:var(--_vv-bg); }
916
- .paper { display:block; flex:none; background:white; box-shadow:var(--vv-shadow,0 2px 8px rgb(0 0 0 / 14%)); margin:auto; }
913
+ .paper { display:block; flex:none; background:white; box-shadow:var(--_vv-shadow); margin:auto; }
917
914
  .paper [data-shape-id] { cursor:pointer; }
918
915
  .paper [data-selected="true"] > [data-geometry] { stroke:var(--_vv-accent) !important; stroke-width:.025 !important; }
919
916
  .inspector-pane { flex:0 0 288px; width:288px; min-width:0; overflow:auto; border-left:1px solid var(--_vv-border); background:var(--_vv-secondary); }
@@ -939,11 +936,11 @@ summary::marker { color:var(--_vv-muted); font-size:10px; }
939
936
  .edit-controls label { display:block; margin-top:8px; }
940
937
  .edit-actions { display:flex; flex-wrap:wrap; gap:4px; margin-top:8px; }
941
938
  .edit-actions button { font-size:11px; padding:3px 7px; }
942
- .edit-actions [data-edit="apply"]:enabled { background:var(--_vv-accent); border-color:var(--_vv-accent); color:var(--vv-accent-ink,#fff); }
939
+ .edit-actions [data-edit="apply"]:enabled { background:var(--_vv-accent); border-color:var(--_vv-accent); color:var(--_vv-accent-ink); }
943
940
  .edit-controls [data-geometry] { min-width:0; margin:8px 0 0; padding:6px; border:1px solid var(--_vv-border); }
944
941
  .edit-controls [data-geometry-field] { display:block; width:100%; min-width:0; margin-top:4px; }
945
- .edit-controls [data-geometry-error] { color:var(--vv-danger,#b42318); }
946
- .edit-controls [data-edit-error] { color:var(--vv-danger,#b42318); }
942
+ .edit-controls [data-geometry-error] { color:var(--_vv-danger); }
943
+ .edit-controls [data-edit-error] { color:var(--_vv-danger); }
947
944
  .edit-controls [data-edit-diagnostics] { max-height:100px; overflow:auto; padding-left:16px; }
948
945
  .layer-controls [data-layer-list] { max-height:240px; overflow:auto; }
949
946
  .layer-controls fieldset { border:1px solid var(--_vv-border); margin:6px 0; padding:6px; min-width:0; }
@@ -1041,19 +1038,49 @@ summary::marker { color:var(--_vv-muted); font-size:10px; }
1041
1038
  `;
1042
1039
 
1043
1040
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/visio/styles/backstage.css?raw
1044
- var backstage_default = "/* Visio's File tab and backstage. */\n:host {\n position: relative;\n}\n/* The shared office-ui-backstage draws the File column; these style Visio's page content. */\n.backstage {\n --office-accent: var(--_vv-accent);\n --office-accent-foreground: var(--vv-accent-ink, #fff);\n}\n.backstage-page h1 {\n margin: 0 0 24px;\n font-size: 34px;\n font-weight: 300;\n}\n.backstage-page h2 {\n margin: 20px 0 8px;\n font-size: 16px;\n font-weight: 600;\n}\n.backstage-file {\n margin-top: 0 !important;\n font-size: 20px !important;\n font-weight: 400 !important;\n overflow-wrap: anywhere;\n}\n.backstage-facts {\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: 8px 24px;\n max-width: 520px;\n margin: 0;\n font-size: 13px;\n}\n.backstage-facts dt {\n color: var(--_vv-muted);\n}\n.backstage-facts dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n.backstage-action {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n width: min(420px, 100%);\n min-height: 64px;\n margin: 0 0 10px;\n padding: 10px 16px;\n text-align: left;\n background: var(--_vv-surface);\n}\n.backstage-action strong {\n font-size: 14px;\n font-weight: 600;\n}\n.backstage-action span,\n.backstage-muted,\n.backstage-note-count {\n color: var(--_vv-muted);\n font-size: 12px;\n}\n.backstage-templates {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n.backstage-templates .backstage-action,\n.backstage-templates ::slotted(*) {\n width: 200px;\n min-height: 120px;\n}\n/* Account: the shared profile editor, then Visio's product information. */\n.backstage-page office-ui-account {\n max-width: 560px;\n}\n.backstage-product {\n margin-top: 24px;\n}\n/* Share with people: a live session between windows of this browser. */\n.share-panel {\n max-width: 560px;\n margin-bottom: 16px;\n}\n.share-panel h2 {\n margin-top: 0 !important;\n}\n.share-field {\n display: grid;\n gap: 4px;\n max-width: 320px;\n margin: 12px 0;\n font-size: 13px;\n}\n.share-room {\n min-height: 30px;\n padding: 2px 8px;\n border: 1px solid var(--_vv-border);\n border-radius: 3px;\n background: var(--_vv-surface);\n color: inherit;\n font: inherit;\n}\n.share-buttons button {\n min-height: 32px;\n padding: 0 16px;\n}\n.share-buttons button[hidden] {\n display: none;\n}\n.share-status {\n min-height: 20px;\n font-size: 13px;\n}\n";
1041
+ var backstage_default = "/* Visio's File tab and backstage. */\n:host {\n position: relative;\n}\n/* The shared office-ui-backstage draws the File column; these style Visio's page content. */\n.backstage-page h1 {\n margin: 0 0 24px;\n font-size: 34px;\n font-weight: 300;\n}\n.backstage-page h2 {\n margin: 20px 0 8px;\n font-size: 16px;\n font-weight: 600;\n}\n.backstage-file {\n margin-top: 0 !important;\n font-size: 20px !important;\n font-weight: 400 !important;\n overflow-wrap: anywhere;\n}\n.backstage-facts {\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: 8px 24px;\n max-width: 520px;\n margin: 0;\n font-size: 13px;\n}\n.backstage-facts dt {\n color: var(--_vv-muted);\n}\n.backstage-facts dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n.backstage-action {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n width: min(420px, 100%);\n min-height: 64px;\n margin: 0 0 10px;\n padding: 10px 16px;\n text-align: left;\n background: var(--_vv-surface);\n}\n.backstage-action strong {\n font-size: 14px;\n font-weight: 600;\n}\n.backstage-action span,\n.backstage-muted,\n.backstage-note-count {\n color: var(--_vv-muted);\n font-size: 12px;\n}\n.backstage-templates {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n.backstage-templates .backstage-action,\n.backstage-templates ::slotted(*) {\n width: 200px;\n min-height: 120px;\n}\n/* Account: the shared profile editor, then Visio's product information. */\n.backstage-page office-ui-account {\n max-width: 560px;\n}\n.backstage-product {\n margin-top: 24px;\n}\n/* Share with people: a live session between windows of this browser. */\n.share-panel {\n max-width: 560px;\n margin-bottom: 16px;\n}\n.share-panel h2 {\n margin-top: 0 !important;\n}\n.share-field {\n display: grid;\n gap: 4px;\n max-width: 320px;\n margin: 12px 0;\n font-size: 13px;\n}\n.share-room {\n min-height: 30px;\n padding: 2px 8px;\n border: 1px solid var(--_vv-border);\n border-radius: 3px;\n background: var(--_vv-surface);\n color: inherit;\n font: inherit;\n}\n.share-buttons button {\n min-height: 32px;\n padding: 0 16px;\n}\n.share-buttons button[hidden] {\n display: none;\n}\n.share-status {\n min-height: 20px;\n font-size: 13px;\n}\n";
1045
1042
 
1046
1043
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/visio/styles/canvas.css?raw
1047
- var canvas_default = "/*\n * Drawing canvas focus. SVG outlines are drawn in drawing units (inches here), so a browser\n * focus ring on a shape becomes a page-sized blob. Shapes show focus with a dashed accent\n * stroke instead, only for keyboard focus; selection keeps its solid accent stroke.\n */\n.paper [data-shape-id]:focus,\n.paper [data-shape-id]:focus-visible {\n outline: none;\n}\n.paper [data-shape-id]:focus-visible > [data-geometry] {\n stroke: var(--vv-focus, var(--_vv-accent)) !important;\n stroke-width: 0.04 !important;\n stroke-dasharray: 0.08 0.05;\n}\n\n.paper [data-line-endpoint],\n.rotation-overlay [data-rotation-handle] {\n fill: var(--_vv-accent);\n stroke: white;\n stroke-width: 1.5px;\n cursor: crosshair;\n touch-action: none;\n pointer-events: all;\n}\n.paper .endpoint-preview,\n.paper .rotation-preview,\n.rotation-overlay .rotation-stem {\n stroke: var(--_vv-accent);\n stroke-width: 1.5px;\n stroke-dasharray: 5 3;\n pointer-events: none;\n}\n\n.rotation-overlay {\n position: absolute;\n z-index: 1;\n pointer-events: none;\n}\n";
1044
+ var canvas_default = "/*\n * Drawing canvas focus. SVG outlines are drawn in drawing units (inches here), so a browser\n * focus ring on a shape becomes a page-sized blob. Shapes show focus with a dashed accent\n * stroke instead, only for keyboard focus; selection keeps its solid accent stroke.\n */\n.paper [data-shape-id]:focus,\n.paper [data-shape-id]:focus-visible {\n outline: none;\n}\n.paper [data-shape-id]:focus-visible > [data-geometry] {\n stroke: var(--_vv-focus) !important;\n stroke-width: 0.04 !important;\n stroke-dasharray: 0.08 0.05;\n}\n\n.paper [data-line-endpoint],\n.rotation-overlay [data-rotation-handle] {\n fill: var(--_vv-accent);\n stroke: white;\n stroke-width: 1.5px;\n cursor: crosshair;\n touch-action: none;\n pointer-events: all;\n}\n.paper .endpoint-preview,\n.paper .rotation-preview,\n.rotation-overlay .rotation-stem {\n stroke: var(--_vv-accent);\n stroke-width: 1.5px;\n stroke-dasharray: 5 3;\n pointer-events: none;\n}\n\n.rotation-overlay {\n position: absolute;\n z-index: 1;\n pointer-events: none;\n}\n";
1048
1045
 
1049
1046
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/visio/styles/ribbon.css?raw
1050
- var ribbon_default = "/*\n * Microsoft Visio ribbon layout on the shared ooxml-ui controls. Viewer theme tokens feed the\n * shared --office-* tokens, so host themes still apply. Loaded after the legacy styles.ts.\n */\n:host {\n --office-foreground: var(--_vv-ink);\n --office-muted-foreground: var(--_vv-muted);\n --office-background: var(--_vv-surface);\n --office-surface: var(--_vv-accent-soft);\n --office-border: var(--_vv-border);\n --office-accent: var(--_vv-accent);\n --office-accent-foreground: var(--vv-accent-ink, #fff);\n --office-ring: var(--vv-focus, var(--_vv-accent));\n --office-font: 'Segoe UI', Arial, sans-serif;\n}\n\n/* Tab row: Quick Access Toolbar, then Visio's tabs. */\n.ribbon-head {\n display: flex;\n align-items: stretch;\n min-width: 0;\n border-bottom: 1px solid var(--_vv-border);\n}\n.qat {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 6px;\n border-right: 1px solid var(--_vv-border);\n}\n.qat office-ui-button {\n --office-target-size: 30px;\n}\n.ribbon-head .ribbon-tabs {\n flex: 0 1 auto;\n min-width: 0;\n height: 36px;\n border-bottom: 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.ribbon-head .ribbon-tabs button {\n flex: none;\n min-height: 35px;\n padding: 6px 12px;\n font-size: 13px;\n}\n\n/* Panels: groups of large commands and three-row stacks, as dense as Visio's. */\n.ribbon-content {\n min-height: 96px;\n padding: 2px 2px 0;\n}\n.ribbon-row {\n display: flex;\n flex-wrap: nowrap;\n align-items: stretch;\n gap: 0;\n padding: 0;\n border: 0;\n background: transparent;\n}\n.ribbon-row office-ui-ribbon-group,\n.tools-content office-ui-ribbon-group {\n min-width: 0;\n}\noffice-ui-ribbon-group office-ui-button,\noffice-ui-ribbon-group office-ui-menu-button {\n --office-target-size: 24px;\n}\noffice-ui-ribbon-group [data-size='large'] {\n --office-target-size: 30px;\n}\noffice-ui-button[variant='stacked']::part(button) {\n min-width: 48px;\n min-height: 66px;\n padding: 2px 6px;\n font-size: 12px;\n}\noffice-ui-menu-button[variant='stacked']::part(button) {\n min-width: 48px;\n min-height: 50px;\n font-size: 12px;\n}\noffice-ui-ribbon-group [data-size='small']::part(button) {\n justify-content: flex-start;\n font-size: 12px;\n}\noffice-ui-ribbon-stack:not([orientation]) {\n justify-content: flex-start;\n padding-top: 2px;\n}\noffice-ui-ribbon-stack:not([orientation]) > * {\n min-height: 24px;\n}\noffice-ui-ribbon-group > office-ui-ribbon-stack > office-ui-ribbon-stack[orientation] {\n min-height: 32px;\n}\noffice-ui-select[data-combo] {\n --office-target-size: 24px;\n}\noffice-ui-menu-button[data-active]::part(button) {\n background: var(--_vv-accent-soft);\n box-shadow: inset 0 0 0 1px var(--_vv-accent);\n}\n[data-unsupported] {\n cursor: not-allowed;\n}\n.ribbon-check {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 24px;\n padding: 0 6px;\n font-size: 12px;\n white-space: nowrap;\n cursor: pointer;\n}\n.ribbon-check[data-unsupported] {\n color: var(--_vv-muted);\n opacity: 0.6;\n}\n.ribbon-hint {\n display: none;\n}\n\n/* Drawing window with optional rulers. */\n.canvas-area {\n display: grid;\n flex: 1;\n min-width: 0;\n min-height: 0;\n grid-template-columns: 0 1fr;\n grid-template-rows: 0 1fr;\n}\n.canvas-area[data-ruler='true'] {\n grid-template-columns: 18px 1fr;\n grid-template-rows: 18px 1fr;\n}\n.canvas-area > .viewport {\n grid-column: 2;\n grid-row: 2;\n}\n.ruler,\n.ruler-corner {\n display: none;\n background: var(--_vv-surface);\n}\n.canvas-area[data-ruler='true'] > .ruler,\n.canvas-area[data-ruler='true'] > .ruler-corner {\n display: block;\n}\n.ruler-corner {\n grid-column: 1;\n grid-row: 1;\n border-right: 1px solid var(--_vv-border);\n border-bottom: 1px solid var(--_vv-border);\n}\n/* The shared office-ui-ruler draws ticks, labels and its own edge. */\n.ruler-h {\n grid-column: 2;\n grid-row: 1;\n}\n.ruler-v {\n grid-column: 1;\n grid-row: 2;\n}\n\n.page-bar {\n display: flex;\n flex: none;\n align-items: stretch;\n min-width: 0;\n border-top: 1px solid var(--_vv-border);\n background: var(--_vv-secondary);\n}\n.page-bar office-ui-menu-button {\n --office-target-size: 28px;\n flex: none;\n padding: 0 2px;\n}\n.page-tabs {\n flex: 1;\n min-width: 0;\n border-top: 0;\n}\noffice-ui-status-bar.status {\n gap: 16px;\n min-height: 29px;\n padding: 0 8px 0 12px;\n font-size: 11px;\n background: var(--_vv-surface);\n color: var(--_vv-muted);\n}\noffice-ui-status-item[value=''] {\n display: none;\n}\noffice-ui-status-item[data-page-status] {\n color: var(--_vv-ink);\n}\n.status-message {\n flex: 1;\n min-width: 0;\n}\n.viewport[data-tool='ellipse'],\n.viewport[data-tool='ellipse'] .paper [data-shape-id],\n.viewport[data-tool='rectangle'],\n.viewport[data-tool='rectangle'] .paper [data-shape-id],\n.viewport[data-tool='line'],\n.viewport[data-tool='line'] .paper [data-shape-id] {\n cursor: crosshair;\n}\n.viewport[data-tool='ellipse'],\n.viewport[data-tool='rectangle'],\n.viewport[data-tool='line'] {\n touch-action: none;\n}\n.draw-preview {\n fill: var(--_vv-accent-soft);\n stroke: var(--_vv-accent);\n stroke-width: 1.5px;\n stroke-dasharray: 4 3;\n pointer-events: none;\n}\n.viewport[data-grid='true'] .paper {\n --_vv-grid-minor: rgb(0 0 0 / 7%);\n --_vv-grid-major: rgb(0 0 0 / 16%);\n background-image:\n linear-gradient(to right, var(--_vv-grid-major) 1px, transparent 1px),\n linear-gradient(to top, var(--_vv-grid-major) 1px, transparent 1px),\n linear-gradient(to right, var(--_vv-grid-minor) 1px, transparent 1px),\n linear-gradient(to top, var(--_vv-grid-minor) 1px, transparent 1px);\n background-size:\n var(--vv-inch, 96px) var(--vv-inch, 96px),\n var(--vv-inch, 96px) var(--vv-inch, 96px),\n calc(var(--vv-inch, 96px) / 4) calc(var(--vv-inch, 96px) / 4),\n calc(var(--vv-inch, 96px) / 4) calc(var(--vv-inch, 96px) / 4);\n background-position: left bottom;\n}\n:host(:fullscreen) {\n width: 100vw;\n height: 100vh;\n}\n\n@media (max-width: 760px) {\n .ribbon-row {\n flex: 1;\n min-width: 0;\n }\n .qat office-ui-button {\n --office-target-size: 44px;\n }\n .ribbon-tools .tools-content office-ui-ribbon-group {\n width: 100%;\n }\n office-ui-status-bar.status {\n gap: 4px;\n min-height: 48px;\n }\n office-ui-status-bar .notes-strip,\n office-ui-status-bar .status-message,\n office-ui-status-item[data-shape-status],\n office-ui-status-item[data-page-status] {\n display: none;\n }\n .zoom-controls {\n flex: 1;\n min-width: 0;\n --office-zoom-slider-width: 0;\n }\n}\n\n/* Visio's Tell me box sits right after the tabs. */\n.tell-me {\n flex: 0 1 280px;\n min-width: 140px;\n margin: 0 8px;\n --office-target-size: 28px;\n}\n.presentation-mode {\n --office-target-size: 24px;\n}\n@media (max-width: 760px) {\n .tell-me {\n display: none;\n }\n}\n";
1047
+ var ribbon_default = "/*\n * Microsoft Visio ribbon layout on the shared ooxml-ui controls. The shared --office-* tokens come\n * from the bridge in styles/theme.ts. Loaded after the legacy styles.ts.\n */\n\n/* Tab row: Quick Access Toolbar, then Visio's tabs. */\n.ribbon-head {\n display: flex;\n align-items: stretch;\n min-width: 0;\n border-bottom: 1px solid var(--_vv-border);\n}\n.qat {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 6px;\n border-right: 1px solid var(--_vv-border);\n}\n.qat office-ui-button {\n --office-target-size: 30px;\n}\n.ribbon-head .ribbon-tabs {\n flex: 0 1 auto;\n min-width: 0;\n height: 36px;\n border-bottom: 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.ribbon-head .ribbon-tabs button {\n flex: none;\n min-height: 35px;\n padding: 6px 12px;\n font-size: 13px;\n}\n\n/* Panels: groups of large commands and three-row stacks, as dense as Visio's. */\n.ribbon-content {\n min-height: 96px;\n padding: 2px 2px 0;\n}\n.ribbon-row {\n display: flex;\n flex-wrap: nowrap;\n align-items: stretch;\n gap: 0;\n padding: 0;\n border: 0;\n background: transparent;\n}\n.ribbon-row office-ui-ribbon-group,\n.tools-content office-ui-ribbon-group {\n min-width: 0;\n}\noffice-ui-ribbon-group office-ui-button,\noffice-ui-ribbon-group office-ui-menu-button {\n --office-target-size: 24px;\n}\noffice-ui-ribbon-group [data-size='large'] {\n --office-target-size: 30px;\n}\noffice-ui-button[variant='stacked']::part(button) {\n min-width: 48px;\n min-height: 66px;\n padding: 2px 6px;\n font-size: 12px;\n}\noffice-ui-menu-button[variant='stacked']::part(button) {\n min-width: 48px;\n min-height: 50px;\n font-size: 12px;\n}\noffice-ui-ribbon-group [data-size='small']::part(button) {\n justify-content: flex-start;\n font-size: 12px;\n}\noffice-ui-ribbon-stack:not([orientation]) {\n justify-content: flex-start;\n padding-top: 2px;\n}\noffice-ui-ribbon-stack:not([orientation]) > * {\n min-height: 24px;\n}\noffice-ui-ribbon-group > office-ui-ribbon-stack > office-ui-ribbon-stack[orientation] {\n min-height: 32px;\n}\noffice-ui-select[data-combo] {\n --office-target-size: 24px;\n}\noffice-ui-menu-button[data-active]::part(button) {\n background: var(--_vv-accent-soft);\n box-shadow: inset 0 0 0 1px var(--_vv-accent);\n}\n[data-unsupported] {\n cursor: not-allowed;\n}\n.ribbon-check {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 24px;\n padding: 0 6px;\n font-size: 12px;\n white-space: nowrap;\n cursor: pointer;\n}\n.ribbon-check[data-unsupported] {\n color: var(--_vv-muted);\n opacity: 0.6;\n}\n.ribbon-hint {\n display: none;\n}\n\n/* Drawing window with optional rulers. */\n.canvas-area {\n display: grid;\n flex: 1;\n min-width: 0;\n min-height: 0;\n grid-template-columns: 0 1fr;\n grid-template-rows: 0 1fr;\n}\n.canvas-area[data-ruler='true'] {\n grid-template-columns: 18px 1fr;\n grid-template-rows: 18px 1fr;\n}\n.canvas-area > .viewport {\n grid-column: 2;\n grid-row: 2;\n}\n.ruler,\n.ruler-corner {\n display: none;\n background: var(--_vv-surface);\n}\n.canvas-area[data-ruler='true'] > .ruler,\n.canvas-area[data-ruler='true'] > .ruler-corner {\n display: block;\n}\n.ruler-corner {\n grid-column: 1;\n grid-row: 1;\n border-right: 1px solid var(--_vv-border);\n border-bottom: 1px solid var(--_vv-border);\n}\n/* The shared office-ui-ruler draws ticks, labels and its own edge. */\n.ruler-h {\n grid-column: 2;\n grid-row: 1;\n}\n.ruler-v {\n grid-column: 1;\n grid-row: 2;\n}\n\n.page-bar {\n display: flex;\n flex: none;\n align-items: stretch;\n min-width: 0;\n border-top: 1px solid var(--_vv-border);\n background: var(--_vv-secondary);\n}\n.page-bar office-ui-menu-button {\n --office-target-size: 28px;\n flex: none;\n padding: 0 2px;\n}\n.page-tabs {\n flex: 1;\n min-width: 0;\n border-top: 0;\n}\noffice-ui-status-bar.status {\n gap: 16px;\n min-height: 29px;\n padding: 0 8px 0 12px;\n font-size: 11px;\n background: var(--_vv-surface);\n color: var(--_vv-muted);\n}\noffice-ui-status-item[value=''] {\n display: none;\n}\noffice-ui-status-item[data-page-status] {\n color: var(--_vv-ink);\n}\n.status-message {\n flex: 1;\n min-width: 0;\n}\n.viewport[data-tool='ellipse'],\n.viewport[data-tool='ellipse'] .paper [data-shape-id],\n.viewport[data-tool='rectangle'],\n.viewport[data-tool='rectangle'] .paper [data-shape-id],\n.viewport[data-tool='line'],\n.viewport[data-tool='line'] .paper [data-shape-id] {\n cursor: crosshair;\n}\n.viewport[data-tool='ellipse'],\n.viewport[data-tool='rectangle'],\n.viewport[data-tool='line'] {\n touch-action: none;\n}\n.draw-preview {\n fill: var(--_vv-accent-soft);\n stroke: var(--_vv-accent);\n stroke-width: 1.5px;\n stroke-dasharray: 4 3;\n pointer-events: none;\n}\n.viewport[data-grid='true'] .paper {\n --_vv-grid-minor: rgb(0 0 0 / 7%);\n --_vv-grid-major: rgb(0 0 0 / 16%);\n background-image:\n linear-gradient(to right, var(--_vv-grid-major) 1px, transparent 1px),\n linear-gradient(to top, var(--_vv-grid-major) 1px, transparent 1px),\n linear-gradient(to right, var(--_vv-grid-minor) 1px, transparent 1px),\n linear-gradient(to top, var(--_vv-grid-minor) 1px, transparent 1px);\n background-size:\n var(--vv-inch, 96px) var(--vv-inch, 96px),\n var(--vv-inch, 96px) var(--vv-inch, 96px),\n calc(var(--vv-inch, 96px) / 4) calc(var(--vv-inch, 96px) / 4),\n calc(var(--vv-inch, 96px) / 4) calc(var(--vv-inch, 96px) / 4);\n background-position: left bottom;\n}\n:host(:fullscreen) {\n width: 100vw;\n height: 100vh;\n}\n\n@media (max-width: 760px) {\n .ribbon-row {\n flex: 1;\n min-width: 0;\n }\n .qat office-ui-button {\n --office-target-size: 44px;\n }\n .ribbon-tools .tools-content office-ui-ribbon-group {\n width: 100%;\n }\n office-ui-status-bar.status {\n gap: 4px;\n min-height: 48px;\n }\n office-ui-status-bar .notes-strip,\n office-ui-status-bar .status-message,\n office-ui-status-item[data-shape-status],\n office-ui-status-item[data-page-status] {\n display: none;\n }\n .zoom-controls {\n flex: 1;\n min-width: 0;\n --office-zoom-slider-width: 0;\n }\n}\n\n/* Visio's Tell me box sits right after the tabs. */\n.tell-me {\n flex: 0 1 280px;\n min-width: 140px;\n margin: 0 8px;\n --office-target-size: 28px;\n}\n.presentation-mode {\n --office-target-size: 24px;\n}\n@media (max-width: 760px) {\n .tell-me {\n display: none;\n }\n}\n";
1051
1048
 
1052
1049
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/visio/styles/shapes.css?raw
1053
1050
  var shapes_default = "/* Visio's Shapes window: stencil views, More/Quick Shapes rows and a two-column master grid. */\n.shapes-pane {\n display: flex;\n flex: 0 0 232px;\n flex-direction: column;\n width: 232px;\n min-width: 0;\n overflow: hidden;\n border-right: 1px solid var(--_vv-border);\n background: var(--_vv-secondary);\n}\n.shapes-pane .pane-heading {\n height: 42px;\n font-size: 18px;\n font-weight: 400;\n color: var(--_vv-accent);\n}\n.pane-collapse {\n min-height: 28px;\n width: 28px;\n padding: 0;\n border-color: transparent;\n background: transparent;\n font-size: 18px;\n line-height: 1;\n}\n.shapes-views {\n display: flex;\n gap: 14px;\n padding: 4px 12px 0;\n border-bottom: 1px solid var(--_vv-border);\n}\n.shapes-views button {\n position: relative;\n min-height: 28px;\n padding: 2px 0 6px;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: var(--_vv-muted);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n.shapes-views button[aria-selected='true'] {\n color: var(--_vv-ink);\n}\n.shapes-views button[aria-selected='true']::after {\n content: '';\n position: absolute;\n inset: auto 0 -1px;\n height: 2px;\n background: var(--_vv-accent);\n}\n#shapes-stencils,\n#shapes-search {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 4px 0 8px;\n}\n.shapes-row {\n display: flex;\n align-items: center;\n width: 100%;\n min-height: 30px;\n padding: 0 12px;\n border: 0;\n border-radius: 0;\n background: transparent;\n font-size: 12px;\n text-align: left;\n}\n.shapes-row::after {\n content: '\u203A';\n margin-left: auto;\n font-size: 15px;\n}\n.stencil-title {\n margin: 2px 0;\n padding: 6px 12px;\n border-left: 3px solid var(--_vv-accent);\n background: var(--_vv-accent-soft);\n font-size: 12px;\n font-weight: 600;\n}\n.masters {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2px;\n margin: 0;\n padding: 4px 6px;\n list-style: none;\n}\n.masters li[hidden] {\n display: none;\n}\n.master {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-height: 40px;\n padding: 4px 6px;\n border-color: transparent;\n background: transparent;\n font-size: 11px;\n line-height: 1.2;\n text-align: left;\n cursor: grab;\n}\n.master svg {\n flex: none;\n width: 28px;\n height: 28px;\n fill: var(--_vv-surface);\n stroke: var(--_vv-accent);\n stroke-width: 1.2;\n stroke-linejoin: round;\n}\n.master[data-unsupported] {\n cursor: not-allowed;\n opacity: 0.45;\n}\n.master[data-unsupported]:hover {\n border-color: transparent;\n background: transparent;\n}\n.shapes-search-field {\n display: block;\n width: calc(100% - 24px);\n margin: 6px 12px;\n}\n.shapes-empty {\n margin: 8px 12px;\n color: var(--_vv-muted);\n font-size: 12px;\n}\n@media (max-width: 760px) {\n .shapes-pane {\n position: absolute;\n inset: 0 auto 0 0;\n z-index: 3;\n width: min(260px, 100%);\n box-shadow: 8px 0 24px #0002;\n }\n .master {\n min-height: 44px;\n }\n}\n.shapes-strip {\n display: flex;\n flex: 0 0 28px;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n width: 28px;\n min-width: 28px;\n padding: 8px 0;\n border: 0;\n border-right: 1px solid var(--_vv-border);\n border-radius: 0;\n background: var(--_vv-secondary);\n color: var(--_vv-accent);\n font-size: 16px;\n}\n.shapes-strip[hidden] {\n display: none;\n}\n.shapes-strip-label {\n writing-mode: vertical-rl;\n color: var(--_vv-ink);\n font-size: 12px;\n}\n/* Visio's floating Pan & Zoom window. */\n.pan-zoom {\n position: absolute;\n right: 16px;\n bottom: 16px;\n z-index: 5;\n width: 240px;\n border: 1px solid var(--_vv-border);\n background: var(--_vv-surface);\n box-shadow: 0 6px 20px rgb(0 0 0 / 18%);\n}\n.pan-zoom[hidden] {\n display: none;\n}\n.pan-zoom-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2px 4px 2px 10px;\n border-bottom: 1px solid var(--_vv-border);\n font-size: 12px;\n font-weight: 600;\n}\n.pan-zoom-close {\n min-height: 24px;\n width: 24px;\n padding: 0;\n border-color: transparent;\n background: transparent;\n}\n.pan-zoom-view {\n display: grid;\n place-items: center;\n height: 180px;\n padding: 8px;\n background: var(--_vv-bg);\n cursor: crosshair;\n touch-action: none;\n}\n.pan-zoom-view svg {\n max-width: 100%;\n max-height: 100%;\n background: #fff;\n box-shadow: 0 1px 3px rgb(0 0 0 / 20%);\n}\n.pan-zoom-frame {\n fill: rgb(220 38 38 / 8%);\n stroke: #dc2626;\n stroke-width: 2px;\n}\n";
1054
1051
 
1052
+ // src/visio/styles/theme.ts
1053
+ var visioThemeAliases = `:host {
1054
+ --_vv-bg:var(--vv-background,var(--office-surface,#eceae8));
1055
+ --_vv-surface:var(--vv-surface,var(--office-background,#fff));
1056
+ --_vv-secondary:var(--vv-secondary,var(--office-surface,#f3f2f1));
1057
+ --_vv-ink:var(--vv-ink,var(--office-foreground,#1f1f1f));
1058
+ --_vv-muted:var(--vv-muted,var(--office-muted-foreground,#605e5c));
1059
+ --_vv-border:var(--vv-border,var(--office-border,#e1dfdd));
1060
+ --_vv-accent:var(--vv-accent,var(--office-accent,#3955a3));
1061
+ --_vv-accent-soft:var(--vv-accent-soft,color-mix(in srgb,var(--_vv-accent) 10%,transparent));
1062
+ --_vv-accent-ink:var(--vv-accent-ink,var(--office-accent-foreground,#fff));
1063
+ --_vv-focus:var(--vv-focus,var(--office-ring,var(--_vv-accent)));
1064
+ --_vv-danger:var(--vv-danger,var(--office-danger,#b42318));
1065
+ --_vv-shadow:var(--vv-shadow,var(--office-shadow,0 2px 8px rgb(0 0 0 / 14%)));
1066
+ }
1067
+ `;
1068
+ var visioThemeBridge = themeBridge(":host > *", {
1069
+ "--office-foreground": "var(--_vv-ink)",
1070
+ "--office-muted-foreground": "var(--_vv-muted)",
1071
+ "--office-background": "var(--_vv-surface)",
1072
+ "--office-surface": "var(--_vv-accent-soft)",
1073
+ "--office-border": "var(--_vv-border)",
1074
+ "--office-accent": "var(--_vv-accent)",
1075
+ "--office-accent-foreground": "var(--_vv-accent-ink)",
1076
+ "--office-ring": "var(--_vv-focus)",
1077
+ "--office-font": "'Segoe UI', Arial, sans-serif"
1078
+ });
1079
+
1055
1080
  // src/visio/styles/index.ts
1056
- var canvasAndRibbonStyles = [ribbon_default, shapes_default, backstage_default, canvas_default].join("\n");
1081
+ var canvasAndRibbonStyles = [ribbon_default, shapes_default, backstage_default, canvas_default, visioThemeBridge].join(
1082
+ "\n"
1083
+ );
1057
1084
 
1058
1085
  // src/visio/ribbon-action.ts
1059
1086
  var RIBBON_ACTION_EVENT = "ribbon-action";
@@ -3687,8 +3714,12 @@ var ViewerShare = class {
3687
3714
  #revision = 0;
3688
3715
  /** The package this window last published or adopted, to skip repeats of it. */
3689
3716
  #last = null;
3717
+ /** The drawing this window last published or adopted, so a local load or edit is sent once. */
3718
+ #shared = null;
3690
3719
  #adopting = false;
3691
3720
  #pending = null;
3721
+ /** Publishes a local drawing the room has not seen; set once the session has settled. */
3722
+ #catchUp = null;
3692
3723
  #starting = false;
3693
3724
  get active() {
3694
3725
  return this.#session !== null;
@@ -3734,6 +3765,8 @@ var ViewerShare = class {
3734
3765
  this.#session?.destroy();
3735
3766
  this.#session = null;
3736
3767
  this.#pending = null;
3768
+ this.#shared = null;
3769
+ this.#catchUp = null;
3737
3770
  this.#revision = 0;
3738
3771
  this.#last = null;
3739
3772
  this.#people.participants = [];
@@ -3753,11 +3786,15 @@ var ViewerShare = class {
3753
3786
  });
3754
3787
  this.#session = session;
3755
3788
  const publish = () => {
3789
+ const { document: document2 } = this.controller.state;
3790
+ if (this.#adopting || this.#pending || document2 === this.#shared || !session.canWrite())
3791
+ return;
3756
3792
  const bytes = this.#localBytes();
3757
- if (!bytes || !session.canWrite()) return;
3793
+ if (!bytes) return;
3758
3794
  adapter.write(session.doc, { bytes, revision: this.#revision }, collab.LOCAL_ORIGIN);
3759
3795
  this.#revision = adapter.read(session.doc).revision;
3760
3796
  this.#last = bytes;
3797
+ this.#shared = document2;
3761
3798
  };
3762
3799
  const adopt = () => {
3763
3800
  if (adapter.isEmpty(session.doc)) return;
@@ -3773,7 +3810,11 @@ var ViewerShare = class {
3773
3810
  if (transaction.origin !== collab.LOCAL_ORIGIN) adopt();
3774
3811
  };
3775
3812
  map.observe(observer);
3776
- const settle = () => adapter.isEmpty(session.doc) ? publish() : adopt();
3813
+ const settle = () => {
3814
+ this.#catchUp = publish;
3815
+ if (adapter.isEmpty(session.doc)) publish();
3816
+ else adopt();
3817
+ };
3777
3818
  const stopReady = session.on("ready", settle);
3778
3819
  const stopPeers = session.on("peers", (peers) => this.#showPeers(peers));
3779
3820
  const stopEvents = this.controller.onEvent((name, detail) => {
@@ -3787,6 +3828,7 @@ var ViewerShare = class {
3787
3828
  stopPeers();
3788
3829
  stopEvents();
3789
3830
  stopState();
3831
+ this.#catchUp = null;
3790
3832
  };
3791
3833
  if (session.canWrite()) settle();
3792
3834
  this.#showPeers(session.peers());
@@ -3811,6 +3853,7 @@ var ViewerShare = class {
3811
3853
  const done = (error) => {
3812
3854
  this.#adopting = false;
3813
3855
  if (error) this.#say(error instanceof Error ? error.message : String(error));
3856
+ else this.#shared = this.controller.state.document;
3814
3857
  };
3815
3858
  this.#adopting = true;
3816
3859
  const run = document2 && edit.sourceAvailable ? this.controller.applyRemoteSource(bytes) : this.controller.load(bytes);
@@ -3818,6 +3861,7 @@ var ViewerShare = class {
3818
3861
  }
3819
3862
  #flush(state) {
3820
3863
  if (this.#pending && !state.edit.busy && !state.loading) this.#apply(this.#pending);
3864
+ else this.#catchUp?.();
3821
3865
  }
3822
3866
  #showPeers(peers) {
3823
3867
  const me = this.profile();
@@ -6226,7 +6270,7 @@ var ViewerCommands = class {
6226
6270
  const state = this.host.controller.state;
6227
6271
  const page2 = state.document?.pages[state.pageIndex];
6228
6272
  if (!page2 || !state.selectedShape || !this.#canEdit(state)) return;
6229
- const command2 = action2.type === "rotate" ? visioQuarterTurnCommand(page2, state.selectedShape.id, action2.direction) : visioLocalRotationShape(page2, state.selectedShape.id) ? {
6273
+ const command2 = action2.type === "rotate" ? visioQuarterTurnCommand(page2, state.selectedShape.id, action2.direction) : visioLocalRotationShape(page2, state.selectedShape.id, false) ? {
6230
6274
  type: "flip-shape",
6231
6275
  pageId: page2.id,
6232
6276
  shapeId: state.selectedShape.id,
@@ -6307,8 +6351,9 @@ var ViewerCommands = class {
6307
6351
  if (this.#tool !== "pointer" && !state.edit.sourceAvailable) this.#tool = "pointer";
6308
6352
  const page2 = state.document?.pages[state.pageIndex];
6309
6353
  const rotating = editing && !!page2 && !!state.selectedShape && !!visioLocalRotationShape(page2, state.selectedShape.id);
6310
- for (const name of ["rotate-left", "rotate-right", "flip-horizontal", "flip-vertical"])
6311
- button(name).disabled = !rotating;
6354
+ for (const name of ["rotate-left", "rotate-right"]) button(name).disabled = !rotating;
6355
+ const flipping = rotating && !!page2 && !!state.selectedShape && !!visioLocalRotationShape(page2, state.selectedShape.id, false);
6356
+ for (const name of ["flip-horizontal", "flip-vertical"]) button(name).disabled = !flipping;
6312
6357
  root.querySelector('[data-menu="rotate"]').disabled = !rotating;
6313
6358
  root.querySelector('[data-menu="position"]').disabled = !rotating;
6314
6359
  button("undo").disabled = !state.edit.canUndo || state.edit.busy || state.loading;
@@ -7264,6 +7309,7 @@ var VisioViewerElement = class extends BaseElement {
7264
7309
  #commands;
7265
7310
  #lineEndpoints;
7266
7311
  #rotationHandle;
7312
+ #handleState;
7267
7313
  #rulers;
7268
7314
  #canvas;
7269
7315
  #panZoom;
@@ -7294,7 +7340,8 @@ var VisioViewerElement = class extends BaseElement {
7294
7340
  super();
7295
7341
  this.#root = this.attachShadow({ mode: "open" });
7296
7342
  registerViewerControls();
7297
- this.#root.innerHTML = `<style>${viewerStyles}${canvasAndRibbonStyles}</style>${viewerChromeTemplate}`;
7343
+ installOfficeUiTheme();
7344
+ this.#root.innerHTML = `<style>${visioThemeAliases}${viewerStyles}${canvasAndRibbonStyles}</style>${viewerChromeTemplate}`;
7298
7345
  const workspace = this.#root.querySelector(".workspace");
7299
7346
  this.#findBar = createFindBar(document);
7300
7347
  const ribbon = createRibbon(document);
@@ -7612,8 +7659,12 @@ var VisioViewerElement = class extends BaseElement {
7612
7659
  if (this.#suspended) return;
7613
7660
  const page2 = state.document?.pages[state.pageIndex];
7614
7661
  const changed = this.#canvas.render(state);
7615
- this.#lineEndpoints.render(state);
7616
- this.#rotationHandle.render(state);
7662
+ const previous = this.#handleState;
7663
+ this.#handleState = state;
7664
+ if (changed || !previous || previous.zoom !== state.zoom || previous.selectedShape !== state.selectedShape || previous.loading !== state.loading || previous.edit.busy !== state.edit.busy || previous.edit.sourceAvailable !== state.edit.sourceAvailable) {
7665
+ this.#lineEndpoints.render(state);
7666
+ this.#rotationHandle.render(state);
7667
+ }
7617
7668
  if (changed) this.#announcement = void 0;
7618
7669
  this.#zoomSlider.value = Math.round(state.zoom * 100);
7619
7670
  this.#zoomSlider.disabled = !page2;
@@ -1,8 +1,9 @@
1
1
  import type { BackstageHost } from './parts.js';
2
2
  export type { BackstageHost, EditorOptions, CalculationMode, IterationSettings } from './parts.js';
3
+ export { participants, type ShareHost } from './pages-share.js';
3
4
  export { compatibilityNotes, formatNotes } from './pages-info.js';
4
5
  export { createTemplateWorkbook, TEMPLATES, type TemplateId } from 'ooxml-core/xlsx/ui';
5
- export type BackstagePage = 'info' | 'new' | 'open' | 'saveAs' | 'print' | 'export' | 'options' | 'customize';
6
+ export type BackstagePage = 'info' | 'new' | 'open' | 'saveAs' | 'print' | 'share' | 'export' | 'options' | 'customize';
6
7
  export interface Backstage {
7
8
  readonly element: HTMLElement;
8
9
  open(page?: BackstagePage): void;
@@ -10,5 +11,7 @@ export interface Backstage {
10
11
  readonly isOpen: boolean;
11
12
  /** Re-renders the open page (after a locale change). */
12
13
  relocalize(): void;
14
+ /** Re-renders `page` when it is the one open (its state changed). */
15
+ refresh(page: BackstagePage): void;
13
16
  }
14
17
  export declare function createBackstage(host: BackstageHost): Backstage;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * File > Share: start or stop co-editing this workbook in a named room and see who is in it. The
3
+ * same panel as Visio's (room name, Start / Stop sharing, status, the shared presence stack); the
4
+ * editor's `collaboration` API does the work.
5
+ */
6
+ import { type PresenceParticipant } from '../../presence.js';
7
+ import type { XlsxCollaborationState } from '../collaboration-types.js';
8
+ import { type PageContext } from './parts.js';
9
+ /** What the Share page needs from the editor. */
10
+ export interface ShareHost {
11
+ state(): XlsxCollaborationState;
12
+ start(roomId: string): Promise<void>;
13
+ stop(): void;
14
+ }
15
+ /** A fresh room name a second window can type: `book-` and six letters or digits. */
16
+ export declare const suggestRoom: () => string;
17
+ export declare function renderShare(page: PageContext): void;
18
+ /** The people in the room as the shared presence stack lists them. */
19
+ export declare function participants(state: XlsxCollaborationState): PresenceParticipant[];
@@ -4,6 +4,7 @@ import type { EditorContext } from 'ooxml-core/xlsx/ui';
4
4
  import type { FileCommand } from '../events.js';
5
5
  import type { SaveState } from '../title-bar.js';
6
6
  import type { TemplateId } from 'ooxml-core/xlsx/ui';
7
+ import type { ShareHost } from './pages-share.js';
7
8
  export type CalculationMode = 'automatic' | 'manual';
8
9
  /** Iterative calculation: maximum iterations and maximum change; undefined when off. */
9
10
  export type IterationSettings = {
@@ -34,6 +35,8 @@ export interface BackstageHost {
34
35
  removePassword?(): void;
35
36
  hiddenActions(): readonly string[];
36
37
  setHiddenActions(ids: string[]): void;
38
+ /** File > Share; without it the page only shows its title. */
39
+ share?: ShareHost;
37
40
  }
38
41
  export interface PageContext {
39
42
  host: BackstageHost;
@@ -1,11 +1,11 @@
1
1
  import { type ChartObject, type ChartViewModel, type ChartPatch, type Color, type ChartGradientEdit, type ChartFillPart } from 'ooxml-core/xlsx';
2
- import type { DiagramFill } from 'ooxml-core/diagram';
2
+ import type { DrawingFill } from 'ooxml-core/drawingml';
3
3
  import type { ChartGradientFill } from 'ooxml-core/chart';
4
4
  /** UI target binding; every model edit and temporary model remains in core. */
5
5
  export interface ChartFillBinding {
6
6
  commandId: string;
7
7
  key(): number | ChartFillPart;
8
- fill(chart: ChartObject): DiagramFill | undefined;
8
+ fill(chart: ChartObject): DrawingFill | undefined;
9
9
  gradient(view: ChartViewModel): ChartGradientFill | undefined;
10
10
  paint(view: ChartViewModel): string | undefined;
11
11
  rectangular(chart: ChartObject): boolean;
@@ -1,9 +1,10 @@
1
- import type { DiagramFill, DrawingGradientGeometryType } from 'ooxml-core/diagram';
1
+ import type { DrawingGradientGeometryType } from 'ooxml-core/diagram';
2
+ import type { DrawingFill } from 'ooxml-core/drawingml';
2
3
  import type { EditorContext } from 'ooxml-core/xlsx/ui';
3
4
  /** A native type field that keeps unsupported imported types visible until explicitly changed. */
4
5
  export declare function createGradientTypeField(ctx: EditorContext, onPick: (type: DrawingGradientGeometryType) => void): {
5
6
  element: HTMLLabelElement;
6
- refresh(fill: Extract<DiagramFill, {
7
+ refresh(fill: Extract<DrawingFill, {
7
8
  kind: 'gradient';
8
9
  }>, disabled: boolean, rectangularMarks?: boolean): void;
9
10
  };
@@ -0,0 +1,9 @@
1
+ import type { CollabSession } from 'ooxml-core/collab';
2
+ import type { XlsxPresence } from 'ooxml-core/xlsx/collab';
3
+ import type { XlsxCollaborationOptions } from './collaboration-types.js';
4
+ /** The two runtime modules sharing needs; loaded only when sharing starts. */
5
+ export type CollabRuntime = [
6
+ typeof import('ooxml-core/collab'),
7
+ typeof import('ooxml-core/xlsx/collab')
8
+ ];
9
+ export declare function createRoomSession(collab: CollabRuntime[0], xlsx: CollabRuntime[1], options: XlsxCollaborationOptions, defaultName: string): CollabSession<XlsxPresence>;
@@ -0,0 +1,41 @@
1
+ import type { CollabSession, CollaborationRole, ConnectionStatus, ProviderFactory } from 'ooxml-core/collab';
2
+ import type { XlsxPresence } from 'ooxml-core/xlsx/collab';
3
+ /**
4
+ * How to join a shared workbook. One transport is used, in this order: `session` (host-owned,
5
+ * never destroyed by the editor), `provider`, `serverUrl` (a y-websocket compatible server), else a
6
+ * BroadcastChannel between tabs and windows of this browser.
7
+ */
8
+ export interface XlsxCollaborationOptions {
9
+ /** Room name: 1-128 letters, digits, hyphens or underscores. Not needed with `session`. */
10
+ roomId?: string;
11
+ /** Base URL of a y-websocket compatible server (`wss://host/collab`); the room is appended. */
12
+ serverUrl?: string;
13
+ /** A provider factory of your own (WebRTC, an existing provider through `externalProvider`). */
14
+ provider?: ProviderFactory;
15
+ /** An existing session; create it with `sanitizePayload: sanitizeXlsxPresence`. */
16
+ session?: CollabSession<XlsxPresence>;
17
+ /** Who this window is. The name defaults to `authorName`, the colour to a palette colour. */
18
+ user?: {
19
+ name?: string;
20
+ color?: string;
21
+ role?: CollaborationRole;
22
+ };
23
+ }
24
+ /** One person in the room, as the title bar and `collaboration-change` list them. */
25
+ export interface XlsxCollaborator {
26
+ clientId: number;
27
+ name: string;
28
+ color: string;
29
+ self: boolean;
30
+ }
31
+ /** Collaboration state, reported by `collaborationState` and the `collaboration-change` event. */
32
+ export interface XlsxCollaborationState {
33
+ active: boolean;
34
+ roomId: string | undefined;
35
+ /** `off` when not sharing; otherwise the provider's connection status. */
36
+ status: ConnectionStatus | 'off';
37
+ /** The first exchange with the room finished. */
38
+ synced: boolean;
39
+ people: XlsxCollaborator[];
40
+ }
41
+ export declare const OFF_STATE: XlsxCollaborationState;
@@ -0,0 +1,56 @@
1
+ import type { CellRange, EditSession, RemoteRange } from 'ooxml-core/xlsx';
2
+ import type { EditHistory, Selection, SelectionModel } from 'ooxml-core/xlsx/ui';
3
+ import { type CollabRuntime } from './collaboration-session.js';
4
+ import type { EditorCore } from './editor-core.js';
5
+ import { type XlsxCollaborationOptions, type XlsxCollaborationState } from './collaboration-types.js';
6
+ /** What the controller needs from the editor. */
7
+ export interface CollaborationHost {
8
+ edit(): EditSession | undefined;
9
+ readonly selection: SelectionModel;
10
+ userName(): string;
11
+ t(key: string, vars?: Record<string, string | number>): string;
12
+ toast(message: string, kind: 'info' | 'warning' | 'error'): void;
13
+ /** Reports a failure as `workbook-error`. */
14
+ error(error: Error): void;
15
+ /** Announces `collaboration-change` and refreshes the title bar. */
16
+ changed(state: XlsxCollaborationState): void;
17
+ setReadOnly(readOnly: boolean): void;
18
+ }
19
+ /** The part of the selection a collaborator sees: the range holding the active cell. */
20
+ export declare function presenceRange(selection: Selection): CellRange;
21
+ export declare class XlsxCollaboration {
22
+ #private;
23
+ private readonly host;
24
+ private readonly load;
25
+ constructor(host: CollaborationHost, load?: () => Promise<CollabRuntime>);
26
+ get active(): boolean;
27
+ /** Joined or joining. */
28
+ get busy(): boolean;
29
+ /** The options of the declarative `collaboration` property, if set. */
30
+ get wanted(): XlsxCollaborationOptions | undefined;
31
+ /**
32
+ * Declarative sharing: while set, the open workbook is shared in that room, and a workbook
33
+ * opened later joins it too (the room's content wins when it already has one). Undefined stops.
34
+ */
35
+ want(options: XlsxCollaborationOptions | undefined): void;
36
+ /** Leaves the room before the workbook is replaced; true when it was shared. */
37
+ suspend(): boolean;
38
+ /** Joins the wanted room with the workbook now open. */
39
+ resume(): void;
40
+ /** Joins a room. Rejects when one is active, no workbook is open or the room is invalid. */
41
+ start(options: XlsxCollaborationOptions): Promise<void>;
42
+ /**
43
+ * Leaves the room and forgets the `collaboration` property. A session the host passed in stays
44
+ * alive; one the editor made is destroyed.
45
+ */
46
+ stop(): void;
47
+ /** Restarts the connection, keeping the shared workbook and queued changes. */
48
+ reconnect(): void;
49
+ /** The binding's history while shared (only this window's edits), else undefined. */
50
+ history(): EditHistory | undefined;
51
+ remoteSelections(): readonly RemoteRange[];
52
+ onRemoteChange(listener: () => void): () => void;
53
+ state(): XlsxCollaborationState;
54
+ }
55
+ /** The controller of one editor, reporting through its toasts, events and render loop. */
56
+ export declare function collaborationFor(core: EditorCore): XlsxCollaboration;
@@ -5,6 +5,7 @@
5
5
  import type { Workbook } from 'ooxml-core/xlsx';
6
6
  import { XlsxEditorApi } from './element-api.js';
7
7
  import type { XlsxEditorEventMap } from './events.js';
8
+ import type { XlsxCollaborationOptions } from './collaboration-types.js';
8
9
  import type { EditorLocale, EditorLocaleInput } from 'ooxml-core/xlsx/ui';
9
10
  import { type EditorThemeMode, type XlsxTheme } from './theme/index.js';
10
11
  /** Theme tokens, applied to the host as `--xve-<kebab-key>` custom properties. */
@@ -53,6 +54,13 @@ export declare class XlsxEditorElement extends XlsxEditorApi {
53
54
  set workbook(value: Workbook | null);
54
55
  /** Unsaved changes since the last load, save or `markClean()`. */
55
56
  get dirty(): boolean;
57
+ /**
58
+ * Shares the open workbook in a room while set: a workbook opened later joins the same room
59
+ * (the room's content wins when it already has a workbook); `null` leaves it. A window joining
60
+ * an existing room still needs a workbook open (`newWorkbook()` is enough).
61
+ */
62
+ get collaboration(): XlsxCollaborationOptions | null;
63
+ set collaboration(value: XlsxCollaborationOptions | null | undefined);
56
64
  get activeSheet(): number;
57
65
  set activeSheet(index: number);
58
66
  }
@@ -1,2 +1,6 @@
1
+ import { type Comment } from 'ooxml-core/xlsx';
1
2
  import type { EditorContext } from 'ooxml-core/xlsx/ui';
3
+ import type { OfficeCommentThread } from '../../comments/types.js';
4
+ /** Excel notes and threaded comments as neutral threads, in sheet order, keyed by address. */
5
+ export declare function excelCommentThreads(comments: readonly Comment[]): OfficeCommentThread[];
2
6
  export declare function openCommentsList(ctx: EditorContext): Promise<string | undefined>;
@@ -1,5 +1,5 @@
1
1
  import type { EditorContext } from 'ooxml-core/xlsx/ui';
2
2
  export declare function openShortcutHelp(ctx: EditorContext): Promise<undefined>;
3
3
  export declare const SUPPORTED_FEATURES: readonly ['Cell editing with undo and redo', 'Formulas calculated by the built-in calculation engine', 'Number formats', 'Conditional formatting display', 'Tables', 'Charts (display and basic editing)', 'Comments and notes', 'Hyperlinks', 'Data validation', 'Sort and filter', 'Freeze panes'];
4
- export declare const UNSUPPORTED_FEATURES: readonly ['Pivot tables and sparklines (kept in the file but not shown)', 'Show Formulas', 'Manual calculation', 'Outline (grouping) for columns', 'Password protection hashes', 'Editing threaded comment replies', 'Macros (VBA is kept in the file but never run)', 'Changing the workbook theme', 'Page Layout view'];
4
+ export declare const UNSUPPORTED_FEATURES: readonly ['Pivot tables (kept in the file but not shown)', 'Creating or editing sparklines (existing ones are shown)', 'Show Formulas', 'Manual calculation', 'Outline (grouping) for columns', 'Password protection hashes', 'Editing threaded comment replies', 'Macros (VBA is kept in the file but never run)', 'Changing the workbook theme', 'Page Layout view'];
5
5
  export declare function openFeatureStatus(ctx: EditorContext): Promise<undefined>;
@@ -11,6 +11,7 @@ import { type DialogRegistry } from 'ooxml-core/xlsx/ui';
11
11
  import { DirtyState } from 'ooxml-core/xlsx/ui';
12
12
  import { type EditorLocale } from 'ooxml-core/xlsx/ui';
13
13
  import type { CalculationMode } from './backstage/index.js';
14
+ import { type XlsxCollaboration } from './collaboration.js';
14
15
  import type { EditorThemeMode, XlsxTheme } from './theme/index.js';
15
16
  /** What the shell exposes back to the core (filled in when the element connects). */
16
17
  export interface ShellHooks {
@@ -41,6 +42,8 @@ export declare class EditorCore {
41
42
  readonly dialogs: DialogRegistry;
42
43
  readonly dirty: DirtyState;
43
44
  readonly ctx: EditorContext;
45
+ /** Co-editing over `ooxml-core/collab`; undo and redo go through it while shared. */
46
+ readonly collab: XlsxCollaboration;
44
47
  private gridController;
45
48
  private readonly modelListeners;
46
49
  private stopSession;
@@ -1,16 +1,19 @@
1
1
  /**
2
2
  * The public methods of `<xlsx-editor>` (load, newWorkbook, save, saveBytes, download, markClean,
3
- * select, getSelection, setActiveSheet, undo, redo, focusGrid). The properties and lifecycle are
3
+ * select, getSelection, setActiveSheet, collaboration, share, undo, redo, focusGrid). The properties and lifecycle are
4
4
  * in component.ts; the state is the EditorCore.
5
5
  */
6
6
  import { EditorCore } from './editor-core.js';
7
7
  import { type FileChrome } from './editor-files.js';
8
+ import type { XlsxCollaborationOptions, XlsxCollaborationState } from './collaboration-types.js';
8
9
  /** Server rendering has no HTMLElement; the class still has to be definable there. */
9
10
  export declare const HTMLElementBase: typeof HTMLElement;
10
11
  export declare class XlsxEditorApi extends HTMLElementBase {
11
12
  protected readonly core: EditorCore;
12
13
  /** Set by the shell once connected. */
13
14
  protected chrome: FileChrome | undefined;
15
+ /** Set by the shell once connected: opens File > Share. */
16
+ protected openShare: (() => void) | undefined;
14
17
  /** Opens .xlsx, .xlsm, .xltx, .xls or .csv bytes; `fileName` helps detection and names the file. */
15
18
  load(bytes: Uint8Array | ArrayBuffer, fileName?: string): Promise<void>;
16
19
  /** Starts a blank workbook named Book1.xlsx. */
@@ -30,6 +33,21 @@ export declare class XlsxEditorApi extends HTMLElementBase {
30
33
  /** The selection as A1 text (`B2:C5`, several ranges joined by commas). */
31
34
  getSelection(): string;
32
35
  setActiveSheet(index: number): void;
36
+ /**
37
+ * Shares the open workbook in a room (see `XlsxCollaborationOptions`). Resolves once joined;
38
+ * the room's workbook replaces this one when the room already has one. Rejects when sharing is
39
+ * already active or no workbook is open.
40
+ */
41
+ startCollaboration(options: XlsxCollaborationOptions): Promise<void>;
42
+ /** Leaves the room (and clears `collaboration`). The workbook stays as it is. */
43
+ stopCollaboration(): void;
44
+ /** Restarts the connection, keeping the shared workbook and changes made offline. */
45
+ reconnectCollaboration(): void;
46
+ /** Who is in the room and how the connection is. */
47
+ get collaborationState(): XlsxCollaborationState;
48
+ /** Opens File > Share, where the user starts or stops sharing and sees who is in the room. */
49
+ share(): void;
50
+ /** Undo the last edit; while shared, only this window's edits are undone. */
33
51
  undo(): void;
34
52
  redo(): void;
35
53
  focusGrid(): void;
@@ -1,4 +1,5 @@
1
1
  import type { Workbook } from 'ooxml-core/xlsx';
2
+ import type { XlsxCollaborationState } from './collaboration-types.js';
2
3
  export type FileCommand = 'new' | 'open' | 'save' | 'saveAs' | 'export' | 'exportCsv' | 'print';
3
4
  export interface FileCommandDetail {
4
5
  command: FileCommand;
@@ -50,11 +51,13 @@ export interface XlsxEditorEventMap {
50
51
  'dirty-change': {
51
52
  dirty: boolean;
52
53
  };
54
+ /** Sharing started or stopped, the connection changed, or someone joined, left or synced. */
55
+ 'collaboration-change': XlsxCollaborationState;
53
56
  }
54
57
  export type XlsxEditorEventName = keyof XlsxEditorEventMap;
55
58
  export type XlsxEditorEventDetail<K extends XlsxEditorEventName> = XlsxEditorEventMap[K];
56
59
  /** Runtime list of every event name; the `satisfies` check keeps it a subset of the map. */
57
- export declare const XLSX_EDITOR_EVENTS: readonly ["workbook-change", "workbook-error", "workbook-warning", "readonly-change", "ribbon-action", "ribbon-customize", "file-command", "selection-change", "sheet-change", "dirty-change"];
60
+ export declare const XLSX_EDITOR_EVENTS: readonly ["workbook-change", "workbook-error", "workbook-warning", "readonly-change", "ribbon-action", "ribbon-customize", "file-command", "selection-change", "sheet-change", "dirty-change", "collaboration-change"];
58
61
  /**
59
62
  * Dispatches a bubbling, composed CustomEvent. Returns false when a cancelable event was canceled
60
63
  * (the `EventTarget.dispatchEvent` contract).
@@ -0,0 +1,3 @@
1
+ import type { GridView } from './grid-view.js';
2
+ /** Adds the remote-selection layer to every quadrant; returns the remover. */
3
+ export declare function installRemoteSelections(view: GridView): () => void;
@@ -0,0 +1,3 @@
1
+ import type { SparklineView } from 'ooxml-core/xlsx';
2
+ /** Builds the `<svg class="xg-spark">` for a `w` x `h` px cell at `zoom` percent. */
3
+ export declare function sparklineSvg(doc: Document, view: SparklineView, w: number, h: number, zoom: number): Element;