docxodus 9.4.0 → 9.5.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
  *
@@ -6449,7 +6774,7 @@ var DocxEditor = class _DocxEditor {
6449
6774
  handle.style.display = "flex";
6450
6775
  handle.style.left = `${Math.max(4, rect.left - 32)}px`;
6451
6776
  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);
6777
+ const preview = blockPreviewText(unit);
6453
6778
  handle.setAttribute("aria-label", preview ? `Move block: ${preview}` : "Move block");
6454
6779
  }
6455
6780
  hideBlockHandle() {
@@ -6460,14 +6785,33 @@ var DocxEditor = class _DocxEditor {
6460
6785
  const source = this.currentBlockDragSource();
6461
6786
  if (source && this.blockDragHandle?.style.display !== "none") this.showBlockHandle(source);
6462
6787
  }
6463
- showDropIndicator(target, position) {
6788
+ /** Draw the drop line on `zone`'s requested edge, or take it away when there is no target. */
6789
+ paintDropIndicator(data) {
6464
6790
  const indicator = this.blockDropIndicator;
6791
+ const zone = data.zone;
6465
6792
  if (!indicator) return;
6466
- const rect = this.unitWrapperOf(target).getBoundingClientRect();
6793
+ if (!zone) {
6794
+ this.hideDropIndicator();
6795
+ return;
6796
+ }
6797
+ const y = Math.round(this.dropEdgeY(zone, data.position === "after" ? "after" : "before") + this.dropZoneShift()) - 1;
6798
+ indicator.style.transform = `translate3d(${Math.round(zone.left)}px, ${y}px, 0)`;
6799
+ indicator.style.width = `${Math.max(24, Math.round(zone.width))}px`;
6467
6800
  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`;
6801
+ }
6802
+ /**
6803
+ * Where to draw the line for an insertion on `position` of `zone` — the MIDDLE of the gap to
6804
+ * the neighbour on that side, not the zone's own border-box edge. A paragraph's `w:spacing`
6805
+ * becomes a CSS margin, which sits outside the box, so drawing on the edge underlines the
6806
+ * block's last line instead of reading as a gap between two blocks. Falls back to the raw edge
6807
+ * at the ends of the flow, and degrades to the same value when blocks are contiguous.
6808
+ */
6809
+ dropEdgeY(zone, position) {
6810
+ const neighbour = this.dropZones[zone.index + (position === "after" ? 1 : -1)];
6811
+ if (!neighbour) {
6812
+ return position === "after" ? zone.bottom + zone.marginAfter / 2 : zone.top - zone.marginBefore / 2;
6813
+ }
6814
+ return position === "after" ? (zone.bottom + neighbour.top) / 2 : (neighbour.bottom + zone.top) / 2;
6471
6815
  }
6472
6816
  hideDropIndicator() {
6473
6817
  if (this.blockDropIndicator) this.blockDropIndicator.style.display = "none";
@@ -6547,45 +6891,75 @@ var DocxEditor = class _DocxEditor {
6547
6891
  if (!sides) return false;
6548
6892
  return position ? sides[position] : sides.before || sides.after;
6549
6893
  }
6894
+ /** Measure every movable block once, at drag start. See `BlockDropZone`. */
6895
+ captureDropZones() {
6896
+ const view = this.container.ownerDocument.defaultView;
6897
+ this.dropZoneScroller = this.scrollContainer();
6898
+ this.dropZoneOrigin = this.scrollOffsetSum();
6899
+ this.dropZones = [];
6900
+ const boxes = [];
6901
+ for (const unit of this.bodyUnitNodes()) {
6902
+ const anchorId = this.isMovableBlockUnit(unit) ? this.anchorIdOf(unit) : null;
6903
+ if (!anchorId) continue;
6904
+ const box = this.unitWrapperOf(unit);
6905
+ const rect = box.getBoundingClientRect();
6906
+ boxes.push(box);
6907
+ this.dropZones.push({
6908
+ unit,
6909
+ anchorId,
6910
+ index: this.dropZones.length,
6911
+ top: rect.top,
6912
+ bottom: rect.bottom,
6913
+ left: rect.left,
6914
+ width: rect.width,
6915
+ marginBefore: 0,
6916
+ marginAfter: 0
6917
+ });
6918
+ }
6919
+ const ends = new Set([0, this.dropZones.length - 1].filter((i) => i >= 0 && i < boxes.length));
6920
+ for (const i of ends) {
6921
+ const style = view?.getComputedStyle(boxes[i]);
6922
+ this.dropZones[i].marginBefore = parseFloat(style?.marginTop ?? "0") || 0;
6923
+ this.dropZones[i].marginAfter = parseFloat(style?.marginBottom ?? "0") || 0;
6924
+ }
6925
+ }
6926
+ scrollOffsetSum() {
6927
+ const view = this.container.ownerDocument.defaultView;
6928
+ return (view?.scrollY ?? 0) + (this.dropZoneScroller?.scrollTop ?? 0);
6929
+ }
6930
+ /** How far the measured boxes have travelled since capture, from scrolling (drag autoscroll). */
6931
+ dropZoneShift() {
6932
+ return this.dropZoneOrigin - this.scrollOffsetSum();
6933
+ }
6550
6934
  /**
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
- }));
6935
+ * Where a drop at `clientY` lands, or null when nothing there is legal.
6936
+ *
6937
+ * Resolution is by VERTICAL GEOMETRY over the measured blocks, not by which element the pointer
6938
+ * is over: the drag handle floats in the page margin, so a drag straight down the gutter — the
6939
+ * natural gesture — never crosses a paragraph box, and element hit testing gave those drags no
6940
+ * indicator and no drop at all. The nearest block by vertical distance is the target; the half
6941
+ * the pointer is in picks the side, snapped to the other side when only that one is legal
6942
+ * (a section break or a cross-block range usually makes exactly one side illegal). When neither
6943
+ * side is legal — the pointer is in a region this block cannot reach — there is no drop, and
6944
+ * nothing is drawn.
6945
+ */
6946
+ resolveDropAt(clientY) {
6947
+ const y = clientY - this.dropZoneShift();
6948
+ let best = null;
6949
+ let bestGap = Infinity;
6950
+ for (const zone of this.dropZones) {
6951
+ const gap = y < zone.top ? zone.top - y : y > zone.bottom ? y - zone.bottom : 0;
6952
+ if (gap < bestGap) {
6953
+ best = zone;
6954
+ bestGap = gap;
6955
+ }
6956
+ if (gap === 0) break;
6588
6957
  }
6958
+ if (!best || best.unit === this.blockDragSource) return null;
6959
+ const preferred = y < (best.top + best.bottom) / 2 ? "before" : "after";
6960
+ if (this.isValidMoveTarget(best.unit, preferred)) return { zone: best, position: preferred };
6961
+ const other = preferred === "before" ? "after" : "before";
6962
+ return this.isValidMoveTarget(best.unit, other) ? { zone: best, position: other } : null;
6589
6963
  }
6590
6964
  closeBlockMoveMenu(restoreFocus = false) {
6591
6965
  if (!this.blockMoveMenu || !this.blockDragHandle) return;
@@ -6760,20 +7134,50 @@ var DocxEditor = class _DocxEditor {
6760
7134
  const source = this.currentBlockDragSource();
6761
7135
  return { type: BLOCK_DRAG_TYPE, sourceAnchorId: source ? this.anchorIdOf(source) : void 0 };
6762
7136
  },
7137
+ // The browser would otherwise ghost the 26px grip, which says nothing about what is moving.
7138
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
7139
+ const source = this.currentBlockDragSource();
7140
+ setCustomNativeDragPreview({
7141
+ nativeSetDragImage,
7142
+ getOffset: pointerOutsideOfPreview({ x: "14px", y: "10px" }),
7143
+ render: ({ container }) => {
7144
+ const chip = doc.createElement("div");
7145
+ chip.className = "docx-block-drag-preview";
7146
+ chip.textContent = source && blockPreviewText(source) || "Move block";
7147
+ container.appendChild(chip);
7148
+ return () => chip.remove();
7149
+ }
7150
+ });
7151
+ },
6763
7152
  onDragStart: () => {
7153
+ const source = this.currentBlockDragSource();
6764
7154
  this.blockDragging = true;
6765
7155
  handle.classList.add("docx-block-dragging");
7156
+ source?.classList.add("docx-block-drag-source");
6766
7157
  this.closeBlockMoveMenu();
6767
- this.refreshBlockMoveTargets(this.currentBlockDragSource());
6768
- this.refreshBlockDropTargets();
7158
+ this.refreshBlockMoveTargets(source);
7159
+ this.captureDropZones();
6769
7160
  },
6770
7161
  onDrop: () => {
6771
7162
  this.blockDragging = false;
6772
7163
  this.blockDragPointerDown = false;
7164
+ this.dropZones = [];
6773
7165
  handle.classList.remove("docx-block-dragging");
7166
+ doc.querySelectorAll(".docx-block-drag-source").forEach((el) => el.classList.remove("docx-block-drag-source"));
6774
7167
  this.hideDropIndicator();
6775
7168
  }
6776
7169
  }));
7170
+ this.blockDragCleanup.push(dropTargetForElements({
7171
+ element: this.editRoot,
7172
+ canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
7173
+ getData: ({ input }) => {
7174
+ const hit = this.resolveDropAt(input.clientY);
7175
+ return hit ? { type: BLOCK_DRAG_TYPE, targetAnchorId: hit.zone.anchorId, position: hit.position, zone: hit.zone } : { type: BLOCK_DRAG_TYPE };
7176
+ },
7177
+ onDragEnter: ({ self }) => this.paintDropIndicator(self.data),
7178
+ onDrag: ({ self }) => this.paintDropIndicator(self.data),
7179
+ onDragLeave: () => this.hideDropIndicator()
7180
+ }));
6777
7181
  this.blockDragCleanup.push(monitorForElements({
6778
7182
  canMonitor: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
6779
7183
  onDrop: ({ source, location: location2 }) => {
@@ -6800,13 +7204,13 @@ var DocxEditor = class _DocxEditor {
6800
7204
  canScroll: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
6801
7205
  getAllowedAxis: () => "vertical"
6802
7206
  }));
6803
- this.refreshBlockDropTargets();
6804
7207
  }
6805
7208
  teardownBlockDrag() {
6806
7209
  this.blockMoveTargetPrefetch?.();
6807
7210
  this.blockMoveTargetPrefetch = null;
6808
7211
  this.blockMoveTargetCache.clear();
6809
- for (const cleanup of this.blockDragTargetCleanup.splice(0)) cleanup();
7212
+ this.dropZones = [];
7213
+ this.dropZoneScroller = null;
6810
7214
  for (const cleanup of this.blockDragCleanup.splice(0)) cleanup();
6811
7215
  this.blockDragHandle?.remove();
6812
7216
  this.blockDropIndicator?.remove();
@@ -6895,17 +7299,17 @@ var DocxEditor = class _DocxEditor {
6895
7299
  bodyRoot.after(this.region.footerBand);
6896
7300
  this.region.refreshAll();
6897
7301
  }
6898
- /** Continuous (non-paginated) mount: inject the converter's styles + body, wire blocks. */
7302
+ /**
7303
+ * Continuous (non-paginated) mount: inject the converter's styles + body, wire blocks.
7304
+ *
7305
+ * The body always gets its own `.docx-body-flow` wrapper — not only when bands are docked.
7306
+ * It is the sheet: the element the viewport gives page geometry to and zooms, and the one
7307
+ * the bands dock around. Without it the container would have to be both the scrolling host
7308
+ * and the scaled page, which are different boxes.
7309
+ */
6899
7310
  mountHtml(fullHtml) {
6900
7311
  const parsed = new DOMParser().parseFromString(fullHtml, "text/html");
6901
7312
  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
7313
  this.container.innerHTML = styles;
6910
7314
  const flow = document.createElement("div");
6911
7315
  flow.className = "docx-body-flow";
@@ -6914,7 +7318,8 @@ var DocxEditor = class _DocxEditor {
6914
7318
  this.editRoot = flow;
6915
7319
  if (this.options.editable) this.wireBlocks(flow);
6916
7320
  this.stampPlanState();
6917
- this.dockBands(flow);
7321
+ if (this.region) this.dockBands(flow);
7322
+ this.viewport.attach(flow, true);
6918
7323
  }
6919
7324
  /** Paginated mount: flow blocks into page boxes via pagination.ts, wire the page clones. */
6920
7325
  mountPaginated(fullHtml) {
@@ -6935,6 +7340,7 @@ var DocxEditor = class _DocxEditor {
6935
7340
  this.editRoot = pageRoot;
6936
7341
  if (this.options.editable) this.wireBlocks(pageRoot);
6937
7342
  if (this.region) this.dockBands(target);
7343
+ this.viewport.attach(pageRoot, false);
6938
7344
  }
6939
7345
  wireBlocks(root) {
6940
7346
  root.querySelectorAll("[data-anchor]").forEach((el) => this.wireBlock(el));
@@ -8743,14 +9149,7 @@ var RIBBON_CSS = `
8743
9149
  SHOULD win.
8744
9150
  (No backticks in this file's comments: the stylesheet is a template literal.) */
8745
9151
  .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
- }
9152
+ .dxr[data-chrome] .dxr-surface { margin: 26px auto; padding: 0 16px 96px; }
8754
9153
  .dxr-surface [contenteditable="true"]:focus {
8755
9154
  outline: 2px solid var(--dxr-accent);
8756
9155
  outline-offset: 2px;
@@ -8762,7 +9161,10 @@ var RIBBON_CSS = `
8762
9161
  so they dock as their own regions. Styled from the same tokens as the ribbon
8763
9162
  so the surface reads as one instrument rather than two apps. */
8764
9163
  .dxr-surface .docx-hf-band {
8765
- margin: 0 0 14px;
9164
+ /* Docked outside the zoomed sheet, so it takes the page's on-screen width from the
9165
+ custom property the viewport publishes rather than stretching to the whole surface. */
9166
+ width: min(100%, var(--docx-sheet-width, 100%));
9167
+ margin: 0 auto 14px;
8766
9168
  padding: 9px 72px 13px;
8767
9169
  border: 1px solid var(--dxr-rule);
8768
9170
  border-left: 2px solid #c2ccd9;
@@ -8770,7 +9172,7 @@ var RIBBON_CSS = `
8770
9172
  background: var(--dxr-sheet);
8771
9173
  }
8772
9174
  .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; }
9175
+ .dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px auto 0; }
8774
9176
  .dxr-surface .docx-hf-chrome {
8775
9177
  display: flex;
8776
9178
  gap: 8px;
@@ -8825,13 +9227,15 @@ var RIBBON_CSS = `
8825
9227
  text-transform: none;
8826
9228
  }
8827
9229
  .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
- }
9230
+ /* The sheet IS the page. The editor's viewport sizes .docx-body-flow to the section's page
9231
+ width and its section wrappers to the authored text column, so the horizontal gutters here
9232
+ are the document's own w:sectPr margins, not a padding this chrome invents; only the
9233
+ vertical breathing room is ours. Centering is left to margin:auto so a page the viewport
9234
+ has zoomed to fit stays centered at its scaled width. */
8833
9235
  .dxr[data-chrome] .dxr-surface[data-view="continuous"] .docx-body-flow {
8834
- padding: 56px 72px;
9236
+ max-width: 100%;
9237
+ margin: 0 auto;
9238
+ padding: 56px 0;
8835
9239
  border-radius: 3px;
8836
9240
  background: var(--dxr-sheet);
8837
9241
  box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
@@ -8910,9 +9314,11 @@ var RIBBON_CSS = `
8910
9314
  .dxr[data-chrome="compact"] .dxr-note { display: none; }
8911
9315
  .dxr[data-chrome="compact"] .dxr-rail { display: none; }
8912
9316
  .dxr[data-chrome="compact"] .dxr-hint { display: none; }
9317
+ /* Compact trims the chrome around the page, never the page: the document's own column width
9318
+ is what the viewport's fit-to-width zoom scales, so a phone shows a whole smaller page
9319
+ instead of a narrower one that breaks its lines somewhere Word never would. */
8913
9320
  .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; }
9321
+ .dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] .docx-body-flow { padding: 22px 0; }
8916
9322
  .dxr[data-chrome="compact"] .dxr-surface .docx-hf-band { padding: 9px 18px 13px; }
8917
9323
  .dxr[data-chrome="compact"] .dxr-surface .docx-hf-chrome,
8918
9324
  .dxr[data-chrome="compact"] .dxr-surface .docx-hf-warning { margin-left: 0; }
@@ -9662,6 +10068,8 @@ var RibbonSurface = class {
9662
10068
  fabricateClasses: this.options.fabricateClasses,
9663
10069
  editable: this.options.editable,
9664
10070
  scale: this.options.scale,
10071
+ columnWidth: this.options.columnWidth,
10072
+ fitToWidth: this.options.fitToWidth,
9665
10073
  onEdit: this.options.onEdit,
9666
10074
  onMove: this.options.onMove,
9667
10075
  paginated,
@@ -11633,8 +12041,12 @@ export {
11633
12041
  ComparisonLogLevel,
11634
12042
  ConflictResolution,
11635
12043
  ContextBoundary,
12044
+ DEFAULT_MARGIN,
12045
+ DEFAULT_PAGE_HEIGHT,
12046
+ DEFAULT_PAGE_WIDTH,
11636
12047
  DiffFormat,
11637
12048
  DocumentElementType,
12049
+ DocumentViewport,
11638
12050
  DocxDiffFormatComparison,
11639
12051
  DocxDiffRevisionGranularity,
11640
12052
  DocxEditor,
@@ -11680,6 +12092,7 @@ export {
11680
12092
  findElementsByType,
11681
12093
  findMovePair,
11682
12094
  findTextOccurrences,
12095
+ fitScale,
11683
12096
  generateAnnotationCss,
11684
12097
  generateAnnotationVisibilityCss,
11685
12098
  getAnnotations,
@@ -11703,7 +12116,10 @@ export {
11703
12116
  mountRibbon,
11704
12117
  openDocxSession2 as openDocxSession,
11705
12118
  paginateHtml,
12119
+ parseSectionDimensions,
11706
12120
  projectAnnotationsOntoHtml,
12121
+ ptToPx,
12122
+ pxToPt,
11707
12123
  removeAnnotation,
11708
12124
  removeAnnotationFromHtml,
11709
12125
  renderBlockHtml,