docxodus 9.4.0 → 9.6.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.
@@ -1328,20 +1328,18 @@ function formatPageNumber(value, format) {
1328
1328
  return (renderer ?? RENDERERS.decimal)(value);
1329
1329
  }
1330
1330
 
1331
- // src/pagination.ts
1331
+ // src/page-geometry.ts
1332
1332
  var DEFAULT_PAGE_WIDTH = 612;
1333
1333
  var DEFAULT_PAGE_HEIGHT = 792;
1334
1334
  var DEFAULT_MARGIN = 72;
1335
- var MAX_FOOTNOTE_AREA_RATIO = 0.6;
1336
- var MIN_BODY_CONTENT_HEIGHT = 72;
1335
+ var DEFAULT_HEADER_FOOTER_HEIGHT = 36;
1337
1336
  function pxToPt(px) {
1338
1337
  return px * 0.75;
1339
1338
  }
1340
1339
  function ptToPx(pt) {
1341
1340
  return pt / 0.75;
1342
1341
  }
1343
- var DEFAULT_HEADER_FOOTER_HEIGHT = 36;
1344
- function parseDimensions(section) {
1342
+ function parseSectionDimensions(section) {
1345
1343
  const pageWidth = parseFloat(section.dataset.pageWidth || "") || DEFAULT_PAGE_WIDTH;
1346
1344
  const pageHeight = parseFloat(section.dataset.pageHeight || "") || DEFAULT_PAGE_HEIGHT;
1347
1345
  const contentWidth = parseFloat(section.dataset.contentWidth || "") || pageWidth - 2 * DEFAULT_MARGIN;
@@ -1365,6 +1363,42 @@ function parseDimensions(section) {
1365
1363
  footerHeight
1366
1364
  };
1367
1365
  }
1366
+ function sectionWrappers(root) {
1367
+ const sections = Array.from(root.querySelectorAll("[data-section-index]"));
1368
+ return sections.length > 0 ? sections : [root];
1369
+ }
1370
+ var MIN_FIT_SCALE = 0.25;
1371
+ function fitScale(availablePx, naturalPt, max = 1) {
1372
+ if (!(availablePx > 0) || !(naturalPt > 0)) return max;
1373
+ const naturalPx = ptToPx(naturalPt);
1374
+ if (naturalPx <= availablePx) return max;
1375
+ return Math.max(MIN_FIT_SCALE, Math.min(max, availablePx / naturalPx));
1376
+ }
1377
+ function applyZoom(el, scale, naturalPt) {
1378
+ if (scale === 1) {
1379
+ el.style.removeProperty("zoom");
1380
+ el.style.removeProperty("transform");
1381
+ el.style.removeProperty("transform-origin");
1382
+ el.style.removeProperty("margin-right");
1383
+ el.style.removeProperty("margin-bottom");
1384
+ return;
1385
+ }
1386
+ const zoomSupported = typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("zoom", "0.5");
1387
+ if (zoomSupported) {
1388
+ el.style.zoom = String(scale);
1389
+ return;
1390
+ }
1391
+ el.style.transform = `scale(${scale})`;
1392
+ el.style.transformOrigin = "top left";
1393
+ if (naturalPt) {
1394
+ el.style.marginRight = `-${ptToPx(naturalPt.width * (1 - scale))}px`;
1395
+ el.style.marginBottom = `-${ptToPx(naturalPt.height * (1 - scale))}px`;
1396
+ }
1397
+ }
1398
+
1399
+ // src/pagination.ts
1400
+ var MAX_FOOTNOTE_AREA_RATIO = 0.6;
1401
+ var MIN_BODY_CONTENT_HEIGHT = 72;
1368
1402
  var PaginationEngine = class {
1369
1403
  /**
1370
1404
  * Creates a new pagination engine.
@@ -1410,7 +1444,7 @@ var PaginationEngine = class {
1410
1444
  const sectionsToProcess = sections.length > 0 ? Array.from(sections) : [this.stagingElement];
1411
1445
  for (const section of sectionsToProcess) {
1412
1446
  const sectionIndex = parseInt(section.dataset.sectionIndex || "0", 10);
1413
- const dims = parseDimensions(section);
1447
+ const dims = parseSectionDimensions(section);
1414
1448
  this.stagingElement.style.visibility = "hidden";
1415
1449
  this.stagingElement.style.position = "absolute";
1416
1450
  this.stagingElement.style.left = "-9999px";
@@ -2708,6 +2742,114 @@ function paginateHtml(html, container, options = {}) {
2708
2742
  return engine.paginate();
2709
2743
  }
2710
2744
 
2745
+ // src/viewport.ts
2746
+ var DocumentViewport = class {
2747
+ constructor(host, options = {}) {
2748
+ this.root = null;
2749
+ /** Natural page size in points — the widest section's PAGE box, which is what must fit. */
2750
+ this.natural = { width: 0, height: 0 };
2751
+ this.observer = null;
2752
+ this.host = host;
2753
+ this.options = {
2754
+ columnWidth: options.columnWidth ?? "section",
2755
+ fitToWidth: options.fitToWidth ?? true,
2756
+ scale: options.scale ?? 1
2757
+ };
2758
+ }
2759
+ /**
2760
+ * Adopt a freshly mounted document root (a continuous flow, or the paginated page stack).
2761
+ * Safe to call on every remount; the previous root is released first.
2762
+ *
2763
+ * `applySectionGeometry` is false for the paginated view, which already builds real page
2764
+ * boxes at the section's dimensions — there the viewport contributes only the fit zoom.
2765
+ */
2766
+ attach(root, applySectionGeometry) {
2767
+ this.release();
2768
+ this.root = root;
2769
+ this.natural = applySectionGeometry ? this.stampSections(root) : this.measurePages(root);
2770
+ this.refresh();
2771
+ if (typeof ResizeObserver !== "undefined") {
2772
+ this.observer = new ResizeObserver(() => this.refresh());
2773
+ this.observer.observe(this.host);
2774
+ }
2775
+ }
2776
+ /** Recompute the fit zoom against the host's current width. */
2777
+ refresh() {
2778
+ if (!this.root) return;
2779
+ const scale = this.scale;
2780
+ applyZoom(this.root, scale, this.natural);
2781
+ this.host.style.setProperty(
2782
+ "--docx-sheet-width",
2783
+ this.natural.width > 0 ? `${ptToPx(this.natural.width) * scale}px` : "100%"
2784
+ );
2785
+ }
2786
+ /** The zoom currently applied (1 = 100%). Reported by the ribbon's anchor rail. */
2787
+ get scale() {
2788
+ if (!this.root) return this.options.scale;
2789
+ return this.options.fitToWidth ? fitScale(this.availableWidthPx(), this.natural.width, this.options.scale) : this.options.scale;
2790
+ }
2791
+ dispose() {
2792
+ this.release();
2793
+ this.root = null;
2794
+ }
2795
+ release() {
2796
+ this.observer?.disconnect();
2797
+ this.observer = null;
2798
+ if (this.root) applyZoom(this.root, 1);
2799
+ this.host.style.removeProperty("--docx-sheet-width");
2800
+ }
2801
+ /** The host's content box, which is the space a page has to fit into. */
2802
+ availableWidthPx() {
2803
+ const style = typeof getComputedStyle === "function" ? getComputedStyle(this.host) : null;
2804
+ const padding = style ? (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0) : 0;
2805
+ return Math.max(0, this.host.clientWidth - padding);
2806
+ }
2807
+ /**
2808
+ * Give each section wrapper its `w:sectPr` geometry: the authored text column, guttered by
2809
+ * the authored margins. The wrapper then measures exactly one page wide, which is what the
2810
+ * sheet chrome paints and what the fit zoom scales.
2811
+ */
2812
+ stampSections(root) {
2813
+ const sections = sectionWrappers(root);
2814
+ if (this.options.columnWidth === "fluid") {
2815
+ root.style.removeProperty("width");
2816
+ for (const section of sections) {
2817
+ section.style.removeProperty("width");
2818
+ section.style.removeProperty("padding-left");
2819
+ section.style.removeProperty("padding-right");
2820
+ }
2821
+ return { width: 0, height: 0 };
2822
+ }
2823
+ let widest = 0;
2824
+ for (const section of sections) {
2825
+ const dims = parseSectionDimensions(section);
2826
+ section.style.width = `${dims.contentWidth}pt`;
2827
+ section.style.paddingLeft = `${dims.marginLeft}pt`;
2828
+ section.style.paddingRight = `${dims.marginRight}pt`;
2829
+ section.style.boxSizing = "content-box";
2830
+ section.style.marginLeft = "auto";
2831
+ section.style.marginRight = "auto";
2832
+ widest = Math.max(widest, dims.pageWidth);
2833
+ }
2834
+ if (widest > 0 && sections[0] !== root) root.style.width = `${widest}pt`;
2835
+ return { width: widest, height: 0 };
2836
+ }
2837
+ /**
2838
+ * The paginated view's page boxes are already page-sized — `pagination.ts` writes each
2839
+ * box's `width` in points — so the widest of those is the natural width. Reading the
2840
+ * inline width rather than the laid-out box keeps this independent of the per-box zoom
2841
+ * pagination may itself have applied.
2842
+ */
2843
+ measurePages(root) {
2844
+ let widest = 0;
2845
+ for (const box of Array.from(root.children)) {
2846
+ const declared = /^([\d.]+)pt$/.exec(box.style.width || "");
2847
+ widest = Math.max(widest, declared ? parseFloat(declared[1]) : pxToPt(box.offsetWidth));
2848
+ }
2849
+ return { width: widest, height: 0 };
2850
+ }
2851
+ };
2852
+
2711
2853
  // src/editor-headerfooter.ts
2712
2854
  var PAGE_FORMAT_LABELS = [
2713
2855
  { value: "", label: "Format\u2026" },
@@ -4796,6 +4938,146 @@ function draggable(args) {
4796
4938
  return once(cleanup);
4797
4939
  }
4798
4940
 
4941
+ // node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js
4942
+ function ownKeys4(e, r) {
4943
+ var t = Object.keys(e);
4944
+ if (Object.getOwnPropertySymbols) {
4945
+ var o = Object.getOwnPropertySymbols(e);
4946
+ r && (o = o.filter(function(r2) {
4947
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
4948
+ })), t.push.apply(t, o);
4949
+ }
4950
+ return t;
4951
+ }
4952
+ function _objectSpread4(e) {
4953
+ for (var r = 1; r < arguments.length; r++) {
4954
+ var t = null != arguments[r] ? arguments[r] : {};
4955
+ r % 2 ? ownKeys4(Object(t), true).forEach(function(r2) {
4956
+ _defineProperty(e, r2, t[r2]);
4957
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys4(Object(t)).forEach(function(r2) {
4958
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
4959
+ });
4960
+ }
4961
+ return e;
4962
+ }
4963
+ function defaultOffset() {
4964
+ return {
4965
+ x: 0,
4966
+ y: 0
4967
+ };
4968
+ }
4969
+ function setCustomNativeDragPreview(_ref) {
4970
+ var render = _ref.render, nativeSetDragImage = _ref.nativeSetDragImage, _ref$getOffset = _ref.getOffset, getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
4971
+ var container = document.createElement("div");
4972
+ if (supportsPopover()) {
4973
+ container.setAttribute("popover", "manual");
4974
+ }
4975
+ Object.assign(container.style, _objectSpread4(_objectSpread4({
4976
+ // Ensuring we don't cause reflow when adding the element to the page
4977
+ // Using `position:fixed` rather than `position:absolute` so we are
4978
+ // positioned on the current viewport.
4979
+ // `position:fixed` also creates a new stacking context, so we don't need to do that here
4980
+ position: "fixed"
4981
+ }, supportsPopover() ? (
4982
+ // needs to come first as it has 'inset: unset' which
4983
+ // needs to be overridden by our top / left values
4984
+ popoverResetUserAgentStyles
4985
+ ) : {
4986
+ // Fallback: using maximum possible z-index so that this element
4987
+ // will always be on top of other positioned content.
4988
+ zIndex: maxZIndex
4989
+ }), {}, {
4990
+ // According to `mdn`, the element can be offscreen:
4991
+ // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
4992
+ //
4993
+ // However, that information does not appear in the specs:
4994
+ // https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-setdragimage-dev
4995
+ //
4996
+ // If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
4997
+ top: 0,
4998
+ left: 0,
4999
+ // Avoiding any additional events caused by the new element (being super safe)
5000
+ pointerEvents: "none"
5001
+ }));
5002
+ document.body.append(container);
5003
+ if (supportsPopover()) {
5004
+ container.showPopover();
5005
+ }
5006
+ var unmount = render({
5007
+ container
5008
+ });
5009
+ queueMicrotask(function() {
5010
+ var previewOffset = getOffset({
5011
+ container
5012
+ });
5013
+ if (isSafari()) {
5014
+ var rect = container.getBoundingClientRect();
5015
+ if (rect.width === 0) {
5016
+ return;
5017
+ }
5018
+ container.style.left = "-".concat(rect.width - 1e-4, "px");
5019
+ }
5020
+ nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);
5021
+ });
5022
+ function cleanup() {
5023
+ unbindMonitor();
5024
+ unmount === null || unmount === void 0 || unmount();
5025
+ document.body.removeChild(container);
5026
+ }
5027
+ var unbindMonitor = monitorForElements({
5028
+ // Remove portal in the dragstart event so that the user will never see it
5029
+ onDragStart: cleanup,
5030
+ // Backup: remove portal when the drop finishes (this would be an error case)
5031
+ onDrop: cleanup
5032
+ });
5033
+ }
5034
+
5035
+ // node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/is-safari-on-ios.js
5036
+ var isSafariOnIOS = once(function isSafariOnIOS2() {
5037
+ if (false) {
5038
+ return false;
5039
+ }
5040
+ return isSafari() && "ontouchend" in document;
5041
+ });
5042
+
5043
+ // node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/center-under-pointer.js
5044
+ var centerUnderPointer = function centerUnderPointer2(_ref) {
5045
+ var container = _ref.container;
5046
+ var rect = container.getBoundingClientRect();
5047
+ return {
5048
+ x: rect.width / 2,
5049
+ y: rect.height / 2
5050
+ };
5051
+ };
5052
+
5053
+ // node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/pointer-outside-of-preview.js
5054
+ function pointerOutsideOfPreview(point) {
5055
+ return function getOffset(_ref) {
5056
+ var container = _ref.container;
5057
+ if (isSafariOnIOS() || isAndroid()) {
5058
+ return centerUnderPointer({
5059
+ container
5060
+ });
5061
+ }
5062
+ Object.assign(container.style, {
5063
+ borderInlineStart: "".concat(point.x, " solid transparent"),
5064
+ borderTop: "".concat(point.y, " solid transparent")
5065
+ });
5066
+ var computed = window.getComputedStyle(container);
5067
+ if (computed.direction === "rtl") {
5068
+ var box = container.getBoundingClientRect();
5069
+ return {
5070
+ x: box.width,
5071
+ y: 0
5072
+ };
5073
+ }
5074
+ return {
5075
+ x: 0,
5076
+ y: 0
5077
+ };
5078
+ };
5079
+ }
5080
+
4799
5081
  // node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/engagement-history.js
4800
5082
  var ledger2 = /* @__PURE__ */ new Map();
4801
5083
  var requested = /* @__PURE__ */ new Set();
@@ -4929,7 +5211,7 @@ function addScrollableAttribute(element) {
4929
5211
  }
4930
5212
 
4931
5213
  // node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/configuration.js
4932
- function ownKeys4(e, r) {
5214
+ function ownKeys5(e, r) {
4933
5215
  var t = Object.keys(e);
4934
5216
  if (Object.getOwnPropertySymbols) {
4935
5217
  var o = Object.getOwnPropertySymbols(e);
@@ -4939,12 +5221,12 @@ function ownKeys4(e, r) {
4939
5221
  }
4940
5222
  return t;
4941
5223
  }
4942
- function _objectSpread4(e) {
5224
+ function _objectSpread5(e) {
4943
5225
  for (var r = 1; r < arguments.length; r++) {
4944
5226
  var t = null != arguments[r] ? arguments[r] : {};
4945
- r % 2 ? ownKeys4(Object(t), true).forEach(function(r2) {
5227
+ r % 2 ? ownKeys5(Object(t), true).forEach(function(r2) {
4946
5228
  _defineProperty(e, r2, t[r2]);
4947
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys4(Object(t)).forEach(function(r2) {
5229
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys5(Object(t)).forEach(function(r2) {
4948
5230
  Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
4949
5231
  });
4950
5232
  }
@@ -4979,7 +5261,7 @@ var maxPixelScrollPerSecond = {
4979
5261
  };
4980
5262
  function getInternalConfig(provided) {
4981
5263
  var _provided$maxScrollSp;
4982
- return _objectSpread4(_objectSpread4({}, baseConfig), {}, {
5264
+ return _objectSpread5(_objectSpread5({}, baseConfig), {}, {
4983
5265
  // only allowing limited control over the config at this stage
4984
5266
  maxPixelScrollPerSecond: maxPixelScrollPerSecond[(_provided$maxScrollSp = provided === null || provided === void 0 ? void 0 : provided.maxScrollSpeed) !== null && _provided$maxScrollSp !== void 0 ? _provided$maxScrollSp : "standard"]
4985
5267
  });
@@ -5463,7 +5745,7 @@ function tryScroll(_ref3) {
5463
5745
  }
5464
5746
 
5465
5747
  // node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/make-api.js
5466
- function ownKeys5(e, r) {
5748
+ function ownKeys6(e, r) {
5467
5749
  var t = Object.keys(e);
5468
5750
  if (Object.getOwnPropertySymbols) {
5469
5751
  var o = Object.getOwnPropertySymbols(e);
@@ -5473,12 +5755,12 @@ function ownKeys5(e, r) {
5473
5755
  }
5474
5756
  return t;
5475
5757
  }
5476
- function _objectSpread5(e) {
5758
+ function _objectSpread6(e) {
5477
5759
  for (var r = 1; r < arguments.length; r++) {
5478
5760
  var t = null != arguments[r] ? arguments[r] : {};
5479
- r % 2 ? ownKeys5(Object(t), true).forEach(function(r2) {
5761
+ r % 2 ? ownKeys6(Object(t), true).forEach(function(r2) {
5480
5762
  _defineProperty(e, r2, t[r2]);
5481
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys5(Object(t)).forEach(function(r2) {
5763
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys6(Object(t)).forEach(function(r2) {
5482
5764
  Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
5483
5765
  });
5484
5766
  }
@@ -5517,7 +5799,7 @@ function makeApi(_ref) {
5517
5799
  }
5518
5800
  function autoScrollWindow() {
5519
5801
  var args = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
5520
- var unique = _objectSpread5({}, args);
5802
+ var unique = _objectSpread6({}, args);
5521
5803
  windowRegistry.add(unique);
5522
5804
  function cleanup() {
5523
5805
  windowRegistry.delete(unique);
@@ -5670,6 +5952,11 @@ function needsRemount(diff, newUnits, oldKinds, threshold = 40) {
5670
5952
  var EDITABLE_TAGS = /* @__PURE__ */ new Set(["P", "H1", "H2", "H3", "H4", "H5", "H6"]);
5671
5953
  var BLOCK_DRAG_TYPE = "docxodus-block";
5672
5954
  var blockDragStyledDocuments = /* @__PURE__ */ new WeakSet();
5955
+ function blockPreviewText(unit) {
5956
+ if (unit.tagName === "TABLE") return "Table";
5957
+ const text = (unit.textContent ?? "").trim().replace(/\s+/g, " ");
5958
+ return text.length > 48 ? `${text.slice(0, 48)}\u2026` : text;
5959
+ }
5673
5960
  function ensureBlockDragStyles(doc) {
5674
5961
  if (blockDragStyledDocuments.has(doc)) return;
5675
5962
  blockDragStyledDocuments.add(doc);
@@ -5684,10 +5971,28 @@ function ensureBlockDragStyles(doc) {
5684
5971
  }
5685
5972
  .docx-block-handle:hover, .docx-block-handle:focus-visible { color: #344054; border-color: #98a2b3; outline: none; }
5686
5973
  .docx-block-handle[aria-pressed="true"] { color: #175cd3; border-color: #84adff; background: #eff8ff; }
5687
- .docx-block-handle.docx-block-dragging { cursor: grabbing; opacity: .78; }
5974
+ .docx-block-handle.docx-block-dragging { cursor: grabbing; opacity: .35; }
5975
+ /* The block being carried. Dimming it is the "a drag is happening" signal that survives the
5976
+ pointer being anywhere on screen \u2014 the drop line only says where, not what. */
5977
+ .docx-block-drag-source { opacity: .38; transition: opacity 120ms ease-out; }
5978
+ /* Positioned by transform so tracking the pointer costs no layout. Flipping display none\u2192block
5979
+ restarts the fade \u2014 one cheap entry animation per appearance, none while it tracks. */
5688
5980
  .docx-block-drop-indicator {
5689
- position: fixed; z-index: 2147482999; display: none; height: 3px; pointer-events: none;
5690
- border-radius: 999px; background: #2e90fa; box-shadow: 0 0 0 1px rgba(255,255,255,.85);
5981
+ position: fixed; top: 0; left: 0; z-index: 2147482999; display: none; height: 0;
5982
+ pointer-events: none; border-top: 2px solid #2e90fa;
5983
+ filter: drop-shadow(0 1px 2px rgba(46,144,250,.5));
5984
+ animation: docx-block-drop-in 110ms ease-out;
5985
+ }
5986
+ .docx-block-drop-indicator::before {
5987
+ content: ""; position: absolute; top: -5px; left: -2px; width: 8px; height: 8px;
5988
+ border-radius: 50%; background: #2e90fa;
5989
+ }
5990
+ @keyframes docx-block-drop-in { from { opacity: 0; } to { opacity: 1; } }
5991
+ .docx-block-drag-preview {
5992
+ max-width: 320px; padding: 6px 10px; border: 1px solid #b2ddff; border-radius: 6px;
5993
+ background: #eff8ff; color: #175cd3; box-shadow: 0 6px 16px rgba(16,24,40,.18);
5994
+ font: 500 13px/1.35 system-ui, sans-serif; white-space: nowrap; overflow: hidden;
5995
+ text-overflow: ellipsis;
5691
5996
  }
5692
5997
  .docx-block-move-menu {
5693
5998
  position: fixed; z-index: 2147483001; display: none; min-width: 150px; padding: 5px;
@@ -6075,7 +6380,11 @@ var DocxEditor = class _DocxEditor {
6075
6380
  this.blockMoveLive = null;
6076
6381
  this.blockDragSource = null;
6077
6382
  this.blockDragCleanup = [];
6078
- this.blockDragTargetCleanup = [];
6383
+ /** Block boxes measured at drag start — see `BlockDropZone`. Empty when no drag is in flight. */
6384
+ this.dropZones = [];
6385
+ /** Combined scroll offset when `dropZones` was measured, and the scroller measured against. */
6386
+ this.dropZoneOrigin = 0;
6387
+ this.dropZoneScroller = null;
6079
6388
  this.blockDragging = false;
6080
6389
  this.blockDragPointerDown = false;
6081
6390
  /** Anchors the current drag source may legally move next to, per the engine's own rules.
@@ -6204,6 +6513,11 @@ var DocxEditor = class _DocxEditor {
6204
6513
  this.handle = handle;
6205
6514
  this.options = options;
6206
6515
  this.editRoot = container;
6516
+ this.viewport = new DocumentViewport(container, {
6517
+ columnWidth: options.columnWidth,
6518
+ fitToWidth: options.fitToWidth,
6519
+ scale: options.scale
6520
+ });
6207
6521
  if (typeof document !== "undefined") {
6208
6522
  document.addEventListener("selectionchange", this.onSelectionChange);
6209
6523
  document.addEventListener("mousedown", this.onMouseDown, true);
@@ -6286,6 +6600,8 @@ var DocxEditor = class _DocxEditor {
6286
6600
  editable: options.editable ?? true,
6287
6601
  paginated: options.paginated ?? false,
6288
6602
  scale: options.scale ?? 1,
6603
+ columnWidth: options.columnWidth ?? "section",
6604
+ fitToWidth: options.fitToWidth ?? true,
6289
6605
  headerFooter: options.headerFooter ?? false,
6290
6606
  blockDrag: options.blockDrag ?? false,
6291
6607
  trackedChanges: options.trackedChanges ?? 0 /* Accept */,
@@ -6342,6 +6658,7 @@ var DocxEditor = class _DocxEditor {
6342
6658
  }
6343
6659
  this.clearDragSelection();
6344
6660
  this.teardownBlockDrag();
6661
+ this.viewport.dispose();
6345
6662
  this.exports.DocxSessionBridge.CloseSession(this.handle);
6346
6663
  }
6347
6664
  /**
@@ -6359,6 +6676,14 @@ var DocxEditor = class _DocxEditor {
6359
6676
  get root() {
6360
6677
  return this.container;
6361
6678
  }
6679
+ /**
6680
+ * The zoom the viewport is currently applying (1 = 100%). Below 1 the page is wider than the
6681
+ * host and has been scaled to fit rather than reflowed — the honest thing to show a user who
6682
+ * is wondering why a phone shows the whole page.
6683
+ */
6684
+ get zoom() {
6685
+ return this.viewport.scale;
6686
+ }
6362
6687
  /**
6363
6688
  * The live `DocxSession` handle backing this editor — the model of record.
6364
6689
  *
@@ -6369,6 +6694,19 @@ var DocxEditor = class _DocxEditor {
6369
6694
  get sessionHandle() {
6370
6695
  return this.handle;
6371
6696
  }
6697
+ /**
6698
+ * Repaint from the live session after it was mutated OUTSIDE the editor's own
6699
+ * commands — a host driving {@link sessionHandle} directly (an agent pipeline,
6700
+ * `raw.replaceXml`, a batch import). Continuous mode patches incrementally from
6701
+ * the render plan (a Unid-preserving single-block mutation repaints just that
6702
+ * block); paginated mode — or anything the reconciler cannot prove — remounts.
6703
+ * The editor cannot observe external mutations, so the host owns calling this
6704
+ * once per mutation batch.
6705
+ */
6706
+ refresh() {
6707
+ this.assertOpen();
6708
+ this.reconcile();
6709
+ }
6372
6710
  /** Move one top-level body block relative to another and repaint from the live session. */
6373
6711
  moveBlock(sourceAnchorId, targetAnchorId, position) {
6374
6712
  this.assertOpen();
@@ -6449,7 +6787,7 @@ var DocxEditor = class _DocxEditor {
6449
6787
  handle.style.display = "flex";
6450
6788
  handle.style.left = `${Math.max(4, rect.left - 32)}px`;
6451
6789
  handle.style.top = `${Math.max(4, rect.top + (unit.tagName === "TABLE" ? 6 : Math.max(0, (rect.height - 28) / 2)))}px`;
6452
- const preview = (unit.textContent ?? "").trim().replace(/\s+/g, " ").slice(0, 48);
6790
+ const preview = blockPreviewText(unit);
6453
6791
  handle.setAttribute("aria-label", preview ? `Move block: ${preview}` : "Move block");
6454
6792
  }
6455
6793
  hideBlockHandle() {
@@ -6460,14 +6798,33 @@ var DocxEditor = class _DocxEditor {
6460
6798
  const source = this.currentBlockDragSource();
6461
6799
  if (source && this.blockDragHandle?.style.display !== "none") this.showBlockHandle(source);
6462
6800
  }
6463
- showDropIndicator(target, position) {
6801
+ /** Draw the drop line on `zone`'s requested edge, or take it away when there is no target. */
6802
+ paintDropIndicator(data) {
6464
6803
  const indicator = this.blockDropIndicator;
6804
+ const zone = data.zone;
6465
6805
  if (!indicator) return;
6466
- const rect = this.unitWrapperOf(target).getBoundingClientRect();
6806
+ if (!zone) {
6807
+ this.hideDropIndicator();
6808
+ return;
6809
+ }
6810
+ const y = Math.round(this.dropEdgeY(zone, data.position === "after" ? "after" : "before") + this.dropZoneShift()) - 1;
6811
+ indicator.style.transform = `translate3d(${Math.round(zone.left)}px, ${y}px, 0)`;
6812
+ indicator.style.width = `${Math.max(24, Math.round(zone.width))}px`;
6467
6813
  indicator.style.display = "block";
6468
- indicator.style.left = `${rect.left}px`;
6469
- indicator.style.top = `${position === "before" ? rect.top - 1 : rect.bottom - 1}px`;
6470
- indicator.style.width = `${Math.max(24, rect.width)}px`;
6814
+ }
6815
+ /**
6816
+ * Where to draw the line for an insertion on `position` of `zone` — the MIDDLE of the gap to
6817
+ * the neighbour on that side, not the zone's own border-box edge. A paragraph's `w:spacing`
6818
+ * becomes a CSS margin, which sits outside the box, so drawing on the edge underlines the
6819
+ * block's last line instead of reading as a gap between two blocks. Falls back to the raw edge
6820
+ * at the ends of the flow, and degrades to the same value when blocks are contiguous.
6821
+ */
6822
+ dropEdgeY(zone, position) {
6823
+ const neighbour = this.dropZones[zone.index + (position === "after" ? 1 : -1)];
6824
+ if (!neighbour) {
6825
+ return position === "after" ? zone.bottom + zone.marginAfter / 2 : zone.top - zone.marginBefore / 2;
6826
+ }
6827
+ return position === "after" ? (zone.bottom + neighbour.top) / 2 : (neighbour.bottom + zone.top) / 2;
6471
6828
  }
6472
6829
  hideDropIndicator() {
6473
6830
  if (this.blockDropIndicator) this.blockDropIndicator.style.display = "none";
@@ -6547,45 +6904,75 @@ var DocxEditor = class _DocxEditor {
6547
6904
  if (!sides) return false;
6548
6905
  return position ? sides[position] : sides.before || sides.after;
6549
6906
  }
6907
+ /** Measure every movable block once, at drag start. See `BlockDropZone`. */
6908
+ captureDropZones() {
6909
+ const view = this.container.ownerDocument.defaultView;
6910
+ this.dropZoneScroller = this.scrollContainer();
6911
+ this.dropZoneOrigin = this.scrollOffsetSum();
6912
+ this.dropZones = [];
6913
+ const boxes = [];
6914
+ for (const unit of this.bodyUnitNodes()) {
6915
+ const anchorId = this.isMovableBlockUnit(unit) ? this.anchorIdOf(unit) : null;
6916
+ if (!anchorId) continue;
6917
+ const box = this.unitWrapperOf(unit);
6918
+ const rect = box.getBoundingClientRect();
6919
+ boxes.push(box);
6920
+ this.dropZones.push({
6921
+ unit,
6922
+ anchorId,
6923
+ index: this.dropZones.length,
6924
+ top: rect.top,
6925
+ bottom: rect.bottom,
6926
+ left: rect.left,
6927
+ width: rect.width,
6928
+ marginBefore: 0,
6929
+ marginAfter: 0
6930
+ });
6931
+ }
6932
+ const ends = new Set([0, this.dropZones.length - 1].filter((i) => i >= 0 && i < boxes.length));
6933
+ for (const i of ends) {
6934
+ const style = view?.getComputedStyle(boxes[i]);
6935
+ this.dropZones[i].marginBefore = parseFloat(style?.marginTop ?? "0") || 0;
6936
+ this.dropZones[i].marginAfter = parseFloat(style?.marginBottom ?? "0") || 0;
6937
+ }
6938
+ }
6939
+ scrollOffsetSum() {
6940
+ const view = this.container.ownerDocument.defaultView;
6941
+ return (view?.scrollY ?? 0) + (this.dropZoneScroller?.scrollTop ?? 0);
6942
+ }
6943
+ /** How far the measured boxes have travelled since capture, from scrolling (drag autoscroll). */
6944
+ dropZoneShift() {
6945
+ return this.dropZoneOrigin - this.scrollOffsetSum();
6946
+ }
6550
6947
  /**
6551
- * The side of `unit` a drop at `clientY` should land on: the half the pointer is in, snapped to
6552
- * the other side when only that one is legal. Snapping rather than refusing keeps a reachable
6553
- * target usable the illegal side is usually illegal only because a section break or a
6554
- * cross-block range sits between the two blocks on that side.
6555
- */
6556
- dropPositionFor(unit, clientY) {
6557
- const rect = unit.getBoundingClientRect();
6558
- const preferred = clientY < rect.top + rect.height / 2 ? "before" : "after";
6559
- if (this.isValidMoveTarget(unit, preferred)) return preferred;
6560
- const other = preferred === "before" ? "after" : "before";
6561
- return this.isValidMoveTarget(unit, other) ? other : preferred;
6562
- }
6563
- refreshBlockDropTargets() {
6564
- for (const cleanup of this.blockDragTargetCleanup.splice(0)) cleanup();
6565
- if (!this.blockDragHandle || this.options.paginated) return;
6566
- for (const unit of this.bodyUnitNodes().filter((el) => this.isMovableBlockUnit(el))) {
6567
- this.blockDragTargetCleanup.push(dropTargetForElements({
6568
- element: unit,
6569
- // A target the engine would refuse is not a drop target at all, so Pragmatic never
6570
- // fires onDragEnter for it and no indicator is drawn over it.
6571
- canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE && source.data.sourceAnchorId !== this.anchorIdOf(unit) && this.isValidMoveTarget(unit),
6572
- getData: ({ input }) => ({
6573
- type: BLOCK_DRAG_TYPE,
6574
- targetAnchorId: this.anchorIdOf(unit),
6575
- position: this.dropPositionFor(unit, input.clientY),
6576
- targetElement: unit
6577
- }),
6578
- onDragEnter: ({ self }) => {
6579
- const pos = self.data.position === "after" ? "after" : "before";
6580
- this.showDropIndicator(unit, pos);
6581
- },
6582
- onDrag: ({ self }) => {
6583
- const pos = self.data.position === "after" ? "after" : "before";
6584
- this.showDropIndicator(unit, pos);
6585
- },
6586
- onDragLeave: () => this.hideDropIndicator()
6587
- }));
6948
+ * Where a drop at `clientY` lands, or null when nothing there is legal.
6949
+ *
6950
+ * Resolution is by VERTICAL GEOMETRY over the measured blocks, not by which element the pointer
6951
+ * is over: the drag handle floats in the page margin, so a drag straight down the gutter — the
6952
+ * natural gesture — never crosses a paragraph box, and element hit testing gave those drags no
6953
+ * indicator and no drop at all. The nearest block by vertical distance is the target; the half
6954
+ * the pointer is in picks the side, snapped to the other side when only that one is legal
6955
+ * (a section break or a cross-block range usually makes exactly one side illegal). When neither
6956
+ * side is legal — the pointer is in a region this block cannot reach — there is no drop, and
6957
+ * nothing is drawn.
6958
+ */
6959
+ resolveDropAt(clientY) {
6960
+ const y = clientY - this.dropZoneShift();
6961
+ let best = null;
6962
+ let bestGap = Infinity;
6963
+ for (const zone of this.dropZones) {
6964
+ const gap = y < zone.top ? zone.top - y : y > zone.bottom ? y - zone.bottom : 0;
6965
+ if (gap < bestGap) {
6966
+ best = zone;
6967
+ bestGap = gap;
6968
+ }
6969
+ if (gap === 0) break;
6588
6970
  }
6971
+ if (!best || best.unit === this.blockDragSource) return null;
6972
+ const preferred = y < (best.top + best.bottom) / 2 ? "before" : "after";
6973
+ if (this.isValidMoveTarget(best.unit, preferred)) return { zone: best, position: preferred };
6974
+ const other = preferred === "before" ? "after" : "before";
6975
+ return this.isValidMoveTarget(best.unit, other) ? { zone: best, position: other } : null;
6589
6976
  }
6590
6977
  closeBlockMoveMenu(restoreFocus = false) {
6591
6978
  if (!this.blockMoveMenu || !this.blockDragHandle) return;
@@ -6760,20 +7147,50 @@ var DocxEditor = class _DocxEditor {
6760
7147
  const source = this.currentBlockDragSource();
6761
7148
  return { type: BLOCK_DRAG_TYPE, sourceAnchorId: source ? this.anchorIdOf(source) : void 0 };
6762
7149
  },
7150
+ // The browser would otherwise ghost the 26px grip, which says nothing about what is moving.
7151
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
7152
+ const source = this.currentBlockDragSource();
7153
+ setCustomNativeDragPreview({
7154
+ nativeSetDragImage,
7155
+ getOffset: pointerOutsideOfPreview({ x: "14px", y: "10px" }),
7156
+ render: ({ container }) => {
7157
+ const chip = doc.createElement("div");
7158
+ chip.className = "docx-block-drag-preview";
7159
+ chip.textContent = source && blockPreviewText(source) || "Move block";
7160
+ container.appendChild(chip);
7161
+ return () => chip.remove();
7162
+ }
7163
+ });
7164
+ },
6763
7165
  onDragStart: () => {
7166
+ const source = this.currentBlockDragSource();
6764
7167
  this.blockDragging = true;
6765
7168
  handle.classList.add("docx-block-dragging");
7169
+ source?.classList.add("docx-block-drag-source");
6766
7170
  this.closeBlockMoveMenu();
6767
- this.refreshBlockMoveTargets(this.currentBlockDragSource());
6768
- this.refreshBlockDropTargets();
7171
+ this.refreshBlockMoveTargets(source);
7172
+ this.captureDropZones();
6769
7173
  },
6770
7174
  onDrop: () => {
6771
7175
  this.blockDragging = false;
6772
7176
  this.blockDragPointerDown = false;
7177
+ this.dropZones = [];
6773
7178
  handle.classList.remove("docx-block-dragging");
7179
+ doc.querySelectorAll(".docx-block-drag-source").forEach((el) => el.classList.remove("docx-block-drag-source"));
6774
7180
  this.hideDropIndicator();
6775
7181
  }
6776
7182
  }));
7183
+ this.blockDragCleanup.push(dropTargetForElements({
7184
+ element: this.editRoot,
7185
+ canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
7186
+ getData: ({ input }) => {
7187
+ const hit = this.resolveDropAt(input.clientY);
7188
+ return hit ? { type: BLOCK_DRAG_TYPE, targetAnchorId: hit.zone.anchorId, position: hit.position, zone: hit.zone } : { type: BLOCK_DRAG_TYPE };
7189
+ },
7190
+ onDragEnter: ({ self }) => this.paintDropIndicator(self.data),
7191
+ onDrag: ({ self }) => this.paintDropIndicator(self.data),
7192
+ onDragLeave: () => this.hideDropIndicator()
7193
+ }));
6777
7194
  this.blockDragCleanup.push(monitorForElements({
6778
7195
  canMonitor: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
6779
7196
  onDrop: ({ source, location: location2 }) => {
@@ -6800,13 +7217,13 @@ var DocxEditor = class _DocxEditor {
6800
7217
  canScroll: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
6801
7218
  getAllowedAxis: () => "vertical"
6802
7219
  }));
6803
- this.refreshBlockDropTargets();
6804
7220
  }
6805
7221
  teardownBlockDrag() {
6806
7222
  this.blockMoveTargetPrefetch?.();
6807
7223
  this.blockMoveTargetPrefetch = null;
6808
7224
  this.blockMoveTargetCache.clear();
6809
- for (const cleanup of this.blockDragTargetCleanup.splice(0)) cleanup();
7225
+ this.dropZones = [];
7226
+ this.dropZoneScroller = null;
6810
7227
  for (const cleanup of this.blockDragCleanup.splice(0)) cleanup();
6811
7228
  this.blockDragHandle?.remove();
6812
7229
  this.blockDropIndicator?.remove();
@@ -6895,17 +7312,17 @@ var DocxEditor = class _DocxEditor {
6895
7312
  bodyRoot.after(this.region.footerBand);
6896
7313
  this.region.refreshAll();
6897
7314
  }
6898
- /** Continuous (non-paginated) mount: inject the converter's styles + body, wire blocks. */
7315
+ /**
7316
+ * Continuous (non-paginated) mount: inject the converter's styles + body, wire blocks.
7317
+ *
7318
+ * The body always gets its own `.docx-body-flow` wrapper — not only when bands are docked.
7319
+ * It is the sheet: the element the viewport gives page geometry to and zooms, and the one
7320
+ * the bands dock around. Without it the container would have to be both the scrolling host
7321
+ * and the scaled page, which are different boxes.
7322
+ */
6899
7323
  mountHtml(fullHtml) {
6900
7324
  const parsed = new DOMParser().parseFromString(fullHtml, "text/html");
6901
7325
  const styles = Array.from(parsed.querySelectorAll("style")).map((s) => s.outerHTML).join("");
6902
- if (!this.region) {
6903
- this.container.innerHTML = styles + parsed.body.innerHTML;
6904
- this.editRoot = this.container;
6905
- if (this.options.editable) this.wireBlocks(this.container);
6906
- this.stampPlanState();
6907
- return;
6908
- }
6909
7326
  this.container.innerHTML = styles;
6910
7327
  const flow = document.createElement("div");
6911
7328
  flow.className = "docx-body-flow";
@@ -6914,7 +7331,8 @@ var DocxEditor = class _DocxEditor {
6914
7331
  this.editRoot = flow;
6915
7332
  if (this.options.editable) this.wireBlocks(flow);
6916
7333
  this.stampPlanState();
6917
- this.dockBands(flow);
7334
+ if (this.region) this.dockBands(flow);
7335
+ this.viewport.attach(flow, true);
6918
7336
  }
6919
7337
  /** Paginated mount: flow blocks into page boxes via pagination.ts, wire the page clones. */
6920
7338
  mountPaginated(fullHtml) {
@@ -6935,6 +7353,7 @@ var DocxEditor = class _DocxEditor {
6935
7353
  this.editRoot = pageRoot;
6936
7354
  if (this.options.editable) this.wireBlocks(pageRoot);
6937
7355
  if (this.region) this.dockBands(target);
7356
+ this.viewport.attach(pageRoot, false);
6938
7357
  }
6939
7358
  wireBlocks(root) {
6940
7359
  root.querySelectorAll("[data-anchor]").forEach((el) => this.wireBlock(el));
@@ -8743,14 +9162,7 @@ var RIBBON_CSS = `
8743
9162
  SHOULD win.
8744
9163
  (No backticks in this file's comments: the stylesheet is a template literal.) */
8745
9164
  .dxr-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch; }
8746
- .dxr[data-chrome] .dxr-surface { max-width: 920px; margin: 26px auto; padding: 0 16px 96px; }
8747
- .dxr-surface[data-view="continuous"] > * { background: var(--dxr-sheet); }
8748
- .dxr[data-chrome] .dxr-surface[data-view="continuous"] {
8749
- padding: 56px 72px;
8750
- border-radius: 3px;
8751
- background: var(--dxr-sheet);
8752
- box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
8753
- }
9165
+ .dxr[data-chrome] .dxr-surface { margin: 26px auto; padding: 0 16px 96px; }
8754
9166
  .dxr-surface [contenteditable="true"]:focus {
8755
9167
  outline: 2px solid var(--dxr-accent);
8756
9168
  outline-offset: 2px;
@@ -8762,7 +9174,10 @@ var RIBBON_CSS = `
8762
9174
  so they dock as their own regions. Styled from the same tokens as the ribbon
8763
9175
  so the surface reads as one instrument rather than two apps. */
8764
9176
  .dxr-surface .docx-hf-band {
8765
- margin: 0 0 14px;
9177
+ /* Docked outside the zoomed sheet, so it takes the page's on-screen width from the
9178
+ custom property the viewport publishes rather than stretching to the whole surface. */
9179
+ width: min(100%, var(--docx-sheet-width, 100%));
9180
+ margin: 0 auto 14px;
8766
9181
  padding: 9px 72px 13px;
8767
9182
  border: 1px solid var(--dxr-rule);
8768
9183
  border-left: 2px solid #c2ccd9;
@@ -8770,7 +9185,7 @@ var RIBBON_CSS = `
8770
9185
  background: var(--dxr-sheet);
8771
9186
  }
8772
9187
  .dxr-surface .docx-hf-band + .docx-body-flow { margin-top: 0; }
8773
- .dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px 0 0; }
9188
+ .dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px auto 0; }
8774
9189
  .dxr-surface .docx-hf-chrome {
8775
9190
  display: flex;
8776
9191
  gap: 8px;
@@ -8825,13 +9240,15 @@ var RIBBON_CSS = `
8825
9240
  text-transform: none;
8826
9241
  }
8827
9242
  .dxr-surface .docx-hf-band[data-hf-inherited] { border-style: dashed; }
8828
- .dxr[data-chrome] .dxr-surface[data-view="continuous"]:has(.docx-body-flow) {
8829
- padding: 0;
8830
- background: transparent;
8831
- box-shadow: none;
8832
- }
9243
+ /* The sheet IS the page. The editor's viewport sizes .docx-body-flow to the section's page
9244
+ width and its section wrappers to the authored text column, so the horizontal gutters here
9245
+ are the document's own w:sectPr margins, not a padding this chrome invents; only the
9246
+ vertical breathing room is ours. Centering is left to margin:auto so a page the viewport
9247
+ has zoomed to fit stays centered at its scaled width. */
8833
9248
  .dxr[data-chrome] .dxr-surface[data-view="continuous"] .docx-body-flow {
8834
- padding: 56px 72px;
9249
+ max-width: 100%;
9250
+ margin: 0 auto;
9251
+ padding: 56px 0;
8835
9252
  border-radius: 3px;
8836
9253
  background: var(--dxr-sheet);
8837
9254
  box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
@@ -8910,9 +9327,11 @@ var RIBBON_CSS = `
8910
9327
  .dxr[data-chrome="compact"] .dxr-note { display: none; }
8911
9328
  .dxr[data-chrome="compact"] .dxr-rail { display: none; }
8912
9329
  .dxr[data-chrome="compact"] .dxr-hint { display: none; }
9330
+ /* Compact trims the chrome around the page, never the page: the document's own column width
9331
+ is what the viewport's fit-to-width zoom scales, so a phone shows a whole smaller page
9332
+ instead of a narrower one that breaks its lines somewhere Word never would. */
8913
9333
  .dxr[data-chrome="compact"] .dxr-surface { margin: 12px auto; padding: 0 10px 64px; }
8914
- .dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] { padding: 22px 18px; }
8915
- .dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] .docx-body-flow { padding: 22px 18px; }
9334
+ .dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] .docx-body-flow { padding: 22px 0; }
8916
9335
  .dxr[data-chrome="compact"] .dxr-surface .docx-hf-band { padding: 9px 18px 13px; }
8917
9336
  .dxr[data-chrome="compact"] .dxr-surface .docx-hf-chrome,
8918
9337
  .dxr[data-chrome="compact"] .dxr-surface .docx-hf-warning { margin-left: 0; }
@@ -9662,6 +10081,8 @@ var RibbonSurface = class {
9662
10081
  fabricateClasses: this.options.fabricateClasses,
9663
10082
  editable: this.options.editable,
9664
10083
  scale: this.options.scale,
10084
+ columnWidth: this.options.columnWidth,
10085
+ fitToWidth: this.options.fitToWidth,
9665
10086
  onEdit: this.options.onEdit,
9666
10087
  onMove: this.options.onMove,
9667
10088
  paginated,
@@ -11633,8 +12054,12 @@ export {
11633
12054
  ComparisonLogLevel,
11634
12055
  ConflictResolution,
11635
12056
  ContextBoundary,
12057
+ DEFAULT_MARGIN,
12058
+ DEFAULT_PAGE_HEIGHT,
12059
+ DEFAULT_PAGE_WIDTH,
11636
12060
  DiffFormat,
11637
12061
  DocumentElementType,
12062
+ DocumentViewport,
11638
12063
  DocxDiffFormatComparison,
11639
12064
  DocxDiffRevisionGranularity,
11640
12065
  DocxEditor,
@@ -11680,6 +12105,7 @@ export {
11680
12105
  findElementsByType,
11681
12106
  findMovePair,
11682
12107
  findTextOccurrences,
12108
+ fitScale,
11683
12109
  generateAnnotationCss,
11684
12110
  generateAnnotationVisibilityCss,
11685
12111
  getAnnotations,
@@ -11703,7 +12129,10 @@ export {
11703
12129
  mountRibbon,
11704
12130
  openDocxSession2 as openDocxSession,
11705
12131
  paginateHtml,
12132
+ parseSectionDimensions,
11706
12133
  projectAnnotationsOntoHtml,
12134
+ ptToPx,
12135
+ pxToPt,
11707
12136
  removeAnnotation,
11708
12137
  removeAnnotationFromHtml,
11709
12138
  renderBlockHtml,