docxodus 9.3.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.
- package/dist/editor.bundle.js +588 -114
- package/dist/editor.d.ts +87 -11
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +317 -100
- package/dist/editor.js.map +1 -1
- package/dist/embed.bundle.js +621 -115
- package/dist/embed.iife.js +621 -115
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/page-geometry.d.ts +74 -0
- package/dist/page-geometry.d.ts.map +1 -0
- package/dist/page-geometry.js +105 -0
- package/dist/page-geometry.js.map +1 -0
- package/dist/pagination.bundle.js +8 -6
- package/dist/pagination.d.ts +2 -25
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +2 -45
- package/dist/pagination.js.map +1 -1
- package/dist/ribbon-chrome.d.ts +1 -1
- package/dist/ribbon-chrome.d.ts.map +1 -1
- package/dist/ribbon-chrome.js +18 -18
- package/dist/ribbon.js +2 -0
- package/dist/ribbon.js.map +1 -1
- package/dist/session.bundle.js +25 -1
- package/dist/session.d.ts +20 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +23 -1
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/viewport.d.ts +80 -0
- package/dist/viewport.d.ts.map +1 -0
- package/dist/viewport.js +139 -0
- package/dist/viewport.js.map +1 -0
- package/dist/wasm/_framework/Docxodus.wasm +0 -0
- package/dist/wasm/_framework/Docxodus.wasm.br +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm.br +0 -0
- package/dist/wasm/_framework/dotnet.boot.js +5 -5
- package/dist/wasm/_framework/dotnet.boot.js.br +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm.br +0 -0
- package/package.json +1 -1
package/dist/embed.bundle.js
CHANGED
|
@@ -491,7 +491,9 @@ var DocxSession = class {
|
|
|
491
491
|
* Table row/column editing, addressed by a cell-paragraph anchor (e.g. one returned from
|
|
492
492
|
* {@link insertTable}'s `created`). Insert clones the reference row/column's widths and starts
|
|
493
493
|
* empty (`created` lists the new cell-paragraph anchors); delete of the last row/column removes
|
|
494
|
-
* the whole table.
|
|
494
|
+
* the whole table. All four are grid-aware: inserting across a merge extends it, deleting
|
|
495
|
+
* through one narrows it, and deleting a vertical merge's lead row promotes the next row to
|
|
496
|
+
* carry it — the grid is never left ragged.
|
|
495
497
|
*/
|
|
496
498
|
insertTableRow(cellAnchorId, position) {
|
|
497
499
|
return JSON.parse(this.wasm.InsertTableRow(this.handle, cellAnchorId, position));
|
|
@@ -505,6 +507,28 @@ var DocxSession = class {
|
|
|
505
507
|
deleteTableColumn(cellAnchorId) {
|
|
506
508
|
return JSON.parse(this.wasm.DeleteTableColumn(this.handle, cellAnchorId));
|
|
507
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Merge the rectangle of cells anchored at `cellAnchorId` running `rowSpan` rows down ×
|
|
512
|
+
* `colSpan` cells right (Word's *Merge Cells*): `w:gridSpan` for the horizontal extent,
|
|
513
|
+
* `w:vMerge` restart/continue for the vertical one. The rectangle must tile the same whole grid
|
|
514
|
+
* columns in every row it covers and must not clip a vertical merge entering from above or
|
|
515
|
+
* continuing below — a partial overlap fails with `invalid_table_merge` instead of tearing the
|
|
516
|
+
* grid. `content` decides what happens to the absorbed cells' content (default `"append"`).
|
|
517
|
+
*/
|
|
518
|
+
mergeCells(cellAnchorId, rowSpan, colSpan, content = "append") {
|
|
519
|
+
return JSON.parse(
|
|
520
|
+
this.wasm.MergeCells(this.handle, cellAnchorId, rowSpan, colSpan, content)
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Split the merged cell at `cellAnchorId` back into unit cells, dropping its `w:gridSpan` and
|
|
525
|
+
* `w:vMerge` markup and restoring one cell per grid column (each taking its `w:tblGrid` width).
|
|
526
|
+
* Addressing a vertical-merge continuation unmerges the whole run. A cell with no merge markup
|
|
527
|
+
* fails with `invalid_table_merge`.
|
|
528
|
+
*/
|
|
529
|
+
unmergeCells(cellAnchorId) {
|
|
530
|
+
return JSON.parse(this.wasm.UnmergeCells(this.handle, cellAnchorId));
|
|
531
|
+
}
|
|
508
532
|
/**
|
|
509
533
|
* Table styling, addressed by a cell-paragraph anchor — the post-insert counterpart of
|
|
510
534
|
* {@link insertTable}'s options (issue #315 Stage A). `setColumnWidths` retunes `w:tblGrid` +
|
|
@@ -1304,20 +1328,18 @@ function formatPageNumber(value, format) {
|
|
|
1304
1328
|
return (renderer ?? RENDERERS.decimal)(value);
|
|
1305
1329
|
}
|
|
1306
1330
|
|
|
1307
|
-
// src/
|
|
1331
|
+
// src/page-geometry.ts
|
|
1308
1332
|
var DEFAULT_PAGE_WIDTH = 612;
|
|
1309
1333
|
var DEFAULT_PAGE_HEIGHT = 792;
|
|
1310
1334
|
var DEFAULT_MARGIN = 72;
|
|
1311
|
-
var
|
|
1312
|
-
var MIN_BODY_CONTENT_HEIGHT = 72;
|
|
1335
|
+
var DEFAULT_HEADER_FOOTER_HEIGHT = 36;
|
|
1313
1336
|
function pxToPt(px) {
|
|
1314
1337
|
return px * 0.75;
|
|
1315
1338
|
}
|
|
1316
1339
|
function ptToPx(pt) {
|
|
1317
1340
|
return pt / 0.75;
|
|
1318
1341
|
}
|
|
1319
|
-
|
|
1320
|
-
function parseDimensions(section) {
|
|
1342
|
+
function parseSectionDimensions(section) {
|
|
1321
1343
|
const pageWidth = parseFloat(section.dataset.pageWidth || "") || DEFAULT_PAGE_WIDTH;
|
|
1322
1344
|
const pageHeight = parseFloat(section.dataset.pageHeight || "") || DEFAULT_PAGE_HEIGHT;
|
|
1323
1345
|
const contentWidth = parseFloat(section.dataset.contentWidth || "") || pageWidth - 2 * DEFAULT_MARGIN;
|
|
@@ -1341,6 +1363,42 @@ function parseDimensions(section) {
|
|
|
1341
1363
|
footerHeight
|
|
1342
1364
|
};
|
|
1343
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;
|
|
1344
1402
|
var PaginationEngine = class {
|
|
1345
1403
|
/**
|
|
1346
1404
|
* Creates a new pagination engine.
|
|
@@ -1386,7 +1444,7 @@ var PaginationEngine = class {
|
|
|
1386
1444
|
const sectionsToProcess = sections.length > 0 ? Array.from(sections) : [this.stagingElement];
|
|
1387
1445
|
for (const section of sectionsToProcess) {
|
|
1388
1446
|
const sectionIndex = parseInt(section.dataset.sectionIndex || "0", 10);
|
|
1389
|
-
const dims =
|
|
1447
|
+
const dims = parseSectionDimensions(section);
|
|
1390
1448
|
this.stagingElement.style.visibility = "hidden";
|
|
1391
1449
|
this.stagingElement.style.position = "absolute";
|
|
1392
1450
|
this.stagingElement.style.left = "-9999px";
|
|
@@ -2684,6 +2742,114 @@ function paginateHtml(html, container, options = {}) {
|
|
|
2684
2742
|
return engine.paginate();
|
|
2685
2743
|
}
|
|
2686
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
|
+
|
|
2687
2853
|
// src/editor-headerfooter.ts
|
|
2688
2854
|
var PAGE_FORMAT_LABELS = [
|
|
2689
2855
|
{ value: "", label: "Format\u2026" },
|
|
@@ -4772,6 +4938,146 @@ function draggable(args) {
|
|
|
4772
4938
|
return once(cleanup);
|
|
4773
4939
|
}
|
|
4774
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
|
+
|
|
4775
5081
|
// node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/engagement-history.js
|
|
4776
5082
|
var ledger2 = /* @__PURE__ */ new Map();
|
|
4777
5083
|
var requested = /* @__PURE__ */ new Set();
|
|
@@ -4905,7 +5211,7 @@ function addScrollableAttribute(element) {
|
|
|
4905
5211
|
}
|
|
4906
5212
|
|
|
4907
5213
|
// node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/configuration.js
|
|
4908
|
-
function
|
|
5214
|
+
function ownKeys5(e, r) {
|
|
4909
5215
|
var t = Object.keys(e);
|
|
4910
5216
|
if (Object.getOwnPropertySymbols) {
|
|
4911
5217
|
var o = Object.getOwnPropertySymbols(e);
|
|
@@ -4915,12 +5221,12 @@ function ownKeys4(e, r) {
|
|
|
4915
5221
|
}
|
|
4916
5222
|
return t;
|
|
4917
5223
|
}
|
|
4918
|
-
function
|
|
5224
|
+
function _objectSpread5(e) {
|
|
4919
5225
|
for (var r = 1; r < arguments.length; r++) {
|
|
4920
5226
|
var t = null != arguments[r] ? arguments[r] : {};
|
|
4921
|
-
r % 2 ?
|
|
5227
|
+
r % 2 ? ownKeys5(Object(t), true).forEach(function(r2) {
|
|
4922
5228
|
_defineProperty(e, r2, t[r2]);
|
|
4923
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) :
|
|
5229
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys5(Object(t)).forEach(function(r2) {
|
|
4924
5230
|
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
4925
5231
|
});
|
|
4926
5232
|
}
|
|
@@ -4955,7 +5261,7 @@ var maxPixelScrollPerSecond = {
|
|
|
4955
5261
|
};
|
|
4956
5262
|
function getInternalConfig(provided) {
|
|
4957
5263
|
var _provided$maxScrollSp;
|
|
4958
|
-
return
|
|
5264
|
+
return _objectSpread5(_objectSpread5({}, baseConfig), {}, {
|
|
4959
5265
|
// only allowing limited control over the config at this stage
|
|
4960
5266
|
maxPixelScrollPerSecond: maxPixelScrollPerSecond[(_provided$maxScrollSp = provided === null || provided === void 0 ? void 0 : provided.maxScrollSpeed) !== null && _provided$maxScrollSp !== void 0 ? _provided$maxScrollSp : "standard"]
|
|
4961
5267
|
});
|
|
@@ -5439,7 +5745,7 @@ function tryScroll(_ref3) {
|
|
|
5439
5745
|
}
|
|
5440
5746
|
|
|
5441
5747
|
// node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/make-api.js
|
|
5442
|
-
function
|
|
5748
|
+
function ownKeys6(e, r) {
|
|
5443
5749
|
var t = Object.keys(e);
|
|
5444
5750
|
if (Object.getOwnPropertySymbols) {
|
|
5445
5751
|
var o = Object.getOwnPropertySymbols(e);
|
|
@@ -5449,12 +5755,12 @@ function ownKeys5(e, r) {
|
|
|
5449
5755
|
}
|
|
5450
5756
|
return t;
|
|
5451
5757
|
}
|
|
5452
|
-
function
|
|
5758
|
+
function _objectSpread6(e) {
|
|
5453
5759
|
for (var r = 1; r < arguments.length; r++) {
|
|
5454
5760
|
var t = null != arguments[r] ? arguments[r] : {};
|
|
5455
|
-
r % 2 ?
|
|
5761
|
+
r % 2 ? ownKeys6(Object(t), true).forEach(function(r2) {
|
|
5456
5762
|
_defineProperty(e, r2, t[r2]);
|
|
5457
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) :
|
|
5763
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys6(Object(t)).forEach(function(r2) {
|
|
5458
5764
|
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
5459
5765
|
});
|
|
5460
5766
|
}
|
|
@@ -5493,7 +5799,7 @@ function makeApi(_ref) {
|
|
|
5493
5799
|
}
|
|
5494
5800
|
function autoScrollWindow() {
|
|
5495
5801
|
var args = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
5496
|
-
var unique =
|
|
5802
|
+
var unique = _objectSpread6({}, args);
|
|
5497
5803
|
windowRegistry.add(unique);
|
|
5498
5804
|
function cleanup() {
|
|
5499
5805
|
windowRegistry.delete(unique);
|
|
@@ -5646,6 +5952,11 @@ function needsRemount(diff, newUnits, oldKinds, threshold = 40) {
|
|
|
5646
5952
|
var EDITABLE_TAGS = /* @__PURE__ */ new Set(["P", "H1", "H2", "H3", "H4", "H5", "H6"]);
|
|
5647
5953
|
var BLOCK_DRAG_TYPE = "docxodus-block";
|
|
5648
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
|
+
}
|
|
5649
5960
|
function ensureBlockDragStyles(doc) {
|
|
5650
5961
|
if (blockDragStyledDocuments.has(doc)) return;
|
|
5651
5962
|
blockDragStyledDocuments.add(doc);
|
|
@@ -5660,10 +5971,28 @@ function ensureBlockDragStyles(doc) {
|
|
|
5660
5971
|
}
|
|
5661
5972
|
.docx-block-handle:hover, .docx-block-handle:focus-visible { color: #344054; border-color: #98a2b3; outline: none; }
|
|
5662
5973
|
.docx-block-handle[aria-pressed="true"] { color: #175cd3; border-color: #84adff; background: #eff8ff; }
|
|
5663
|
-
.docx-block-handle.docx-block-dragging { cursor: grabbing; opacity: .
|
|
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. */
|
|
5664
5980
|
.docx-block-drop-indicator {
|
|
5665
|
-
position: fixed; z-index: 2147482999; display: none; height:
|
|
5666
|
-
|
|
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;
|
|
5667
5996
|
}
|
|
5668
5997
|
.docx-block-move-menu {
|
|
5669
5998
|
position: fixed; z-index: 2147483001; display: none; min-width: 150px; padding: 5px;
|
|
@@ -6051,12 +6380,22 @@ var DocxEditor = class _DocxEditor {
|
|
|
6051
6380
|
this.blockMoveLive = null;
|
|
6052
6381
|
this.blockDragSource = null;
|
|
6053
6382
|
this.blockDragCleanup = [];
|
|
6054
|
-
|
|
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;
|
|
6055
6388
|
this.blockDragging = false;
|
|
6056
6389
|
this.blockDragPointerDown = false;
|
|
6057
6390
|
/** Anchors the current drag source may legally move next to, per the engine's own rules.
|
|
6058
6391
|
* Null when the bridge predates ValidMoveTargets — then every block is offered, as before. */
|
|
6059
6392
|
this.blockMoveTargets = null;
|
|
6393
|
+
/** Memoized `ValidMoveTargets` answers, keyed by source anchor and dropped whenever an edit
|
|
6394
|
+
* lands. The legal-target set is a property of the document, so hovering back and forth over
|
|
6395
|
+
* the same blocks between edits must not re-ask the engine. */
|
|
6396
|
+
this.blockMoveTargetCache = /* @__PURE__ */ new Map();
|
|
6397
|
+
/** Cancels the pending idle prefetch of the hovered block's targets — see `showBlockHandle`. */
|
|
6398
|
+
this.blockMoveTargetPrefetch = null;
|
|
6060
6399
|
/** Why the last move was refused, verbatim from the engine — diagnostics, not announcement copy. */
|
|
6061
6400
|
this.lastMoveError = null;
|
|
6062
6401
|
/**
|
|
@@ -6174,6 +6513,11 @@ var DocxEditor = class _DocxEditor {
|
|
|
6174
6513
|
this.handle = handle;
|
|
6175
6514
|
this.options = options;
|
|
6176
6515
|
this.editRoot = container;
|
|
6516
|
+
this.viewport = new DocumentViewport(container, {
|
|
6517
|
+
columnWidth: options.columnWidth,
|
|
6518
|
+
fitToWidth: options.fitToWidth,
|
|
6519
|
+
scale: options.scale
|
|
6520
|
+
});
|
|
6177
6521
|
if (typeof document !== "undefined") {
|
|
6178
6522
|
document.addEventListener("selectionchange", this.onSelectionChange);
|
|
6179
6523
|
document.addEventListener("mousedown", this.onMouseDown, true);
|
|
@@ -6256,6 +6600,8 @@ var DocxEditor = class _DocxEditor {
|
|
|
6256
6600
|
editable: options.editable ?? true,
|
|
6257
6601
|
paginated: options.paginated ?? false,
|
|
6258
6602
|
scale: options.scale ?? 1,
|
|
6603
|
+
columnWidth: options.columnWidth ?? "section",
|
|
6604
|
+
fitToWidth: options.fitToWidth ?? true,
|
|
6259
6605
|
headerFooter: options.headerFooter ?? false,
|
|
6260
6606
|
blockDrag: options.blockDrag ?? false,
|
|
6261
6607
|
trackedChanges: options.trackedChanges ?? 0 /* Accept */,
|
|
@@ -6312,6 +6658,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
6312
6658
|
}
|
|
6313
6659
|
this.clearDragSelection();
|
|
6314
6660
|
this.teardownBlockDrag();
|
|
6661
|
+
this.viewport.dispose();
|
|
6315
6662
|
this.exports.DocxSessionBridge.CloseSession(this.handle);
|
|
6316
6663
|
}
|
|
6317
6664
|
/**
|
|
@@ -6329,6 +6676,14 @@ var DocxEditor = class _DocxEditor {
|
|
|
6329
6676
|
get root() {
|
|
6330
6677
|
return this.container;
|
|
6331
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
|
+
}
|
|
6332
6687
|
/**
|
|
6333
6688
|
* The live `DocxSession` handle backing this editor — the model of record.
|
|
6334
6689
|
*
|
|
@@ -6357,8 +6712,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
6357
6712
|
return true;
|
|
6358
6713
|
}
|
|
6359
6714
|
const destination = res.created?.[0] ?? res.modified?.[0];
|
|
6360
|
-
|
|
6361
|
-
else this.reconcile();
|
|
6715
|
+
this.reconcile();
|
|
6362
6716
|
const moved = destination ? this.bodyUnitNodes().find((el) => el.getAttribute("data-anchor") === destination.unid) : null;
|
|
6363
6717
|
if (moved) {
|
|
6364
6718
|
moved.classList.add("docx-block-move-flash");
|
|
@@ -6383,7 +6737,12 @@ var DocxEditor = class _DocxEditor {
|
|
|
6383
6737
|
const node = target instanceof Node ? target : null;
|
|
6384
6738
|
const el = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
|
|
6385
6739
|
if (!el || !this.editRoot.contains(el)) return null;
|
|
6386
|
-
|
|
6740
|
+
let unit = null;
|
|
6741
|
+
for (let candidate = el.closest("[data-anchor]"); candidate && this.editRoot.contains(candidate); candidate = candidate.parentElement?.closest("[data-anchor]") ?? null) {
|
|
6742
|
+
unit = candidate;
|
|
6743
|
+
}
|
|
6744
|
+
if (!unit || unit.closest("section.footnotes, section.endnotes")) return null;
|
|
6745
|
+
return unit;
|
|
6387
6746
|
}
|
|
6388
6747
|
isMovableBlockUnit(unit) {
|
|
6389
6748
|
if (!unit || !this.anchorIdOf(unit)) return false;
|
|
@@ -6405,18 +6764,18 @@ var DocxEditor = class _DocxEditor {
|
|
|
6405
6764
|
if (!handle || !this.isMovableBlockUnit(unit)) return;
|
|
6406
6765
|
const changed = unit !== this.blockDragSource;
|
|
6407
6766
|
this.blockDragSource = unit;
|
|
6408
|
-
|
|
6409
|
-
if (
|
|
6767
|
+
const known = this.blockMoveTargetsFor(unit, { cachedOnly: true });
|
|
6768
|
+
if (known?.size === 0) {
|
|
6410
6769
|
handle.style.display = "none";
|
|
6411
6770
|
return;
|
|
6412
6771
|
}
|
|
6772
|
+
if (changed && known === void 0) this.prefetchBlockMoveTargets(unit);
|
|
6413
6773
|
const rect = unit.getBoundingClientRect();
|
|
6414
6774
|
handle.style.display = "flex";
|
|
6415
6775
|
handle.style.left = `${Math.max(4, rect.left - 32)}px`;
|
|
6416
6776
|
handle.style.top = `${Math.max(4, rect.top + (unit.tagName === "TABLE" ? 6 : Math.max(0, (rect.height - 28) / 2)))}px`;
|
|
6417
|
-
const preview = (unit
|
|
6777
|
+
const preview = blockPreviewText(unit);
|
|
6418
6778
|
handle.setAttribute("aria-label", preview ? `Move block: ${preview}` : "Move block");
|
|
6419
|
-
if (changed) this.refreshBlockDropTargets();
|
|
6420
6779
|
}
|
|
6421
6780
|
hideBlockHandle() {
|
|
6422
6781
|
if (this.blockDragging || this.blockMoveMenu?.style.display === "block") return;
|
|
@@ -6426,14 +6785,33 @@ var DocxEditor = class _DocxEditor {
|
|
|
6426
6785
|
const source = this.currentBlockDragSource();
|
|
6427
6786
|
if (source && this.blockDragHandle?.style.display !== "none") this.showBlockHandle(source);
|
|
6428
6787
|
}
|
|
6429
|
-
|
|
6788
|
+
/** Draw the drop line on `zone`'s requested edge, or take it away when there is no target. */
|
|
6789
|
+
paintDropIndicator(data) {
|
|
6430
6790
|
const indicator = this.blockDropIndicator;
|
|
6791
|
+
const zone = data.zone;
|
|
6431
6792
|
if (!indicator) return;
|
|
6432
|
-
|
|
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`;
|
|
6433
6800
|
indicator.style.display = "block";
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
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;
|
|
6437
6815
|
}
|
|
6438
6816
|
hideDropIndicator() {
|
|
6439
6817
|
if (this.blockDropIndicator) this.blockDropIndicator.style.display = "none";
|
|
@@ -6453,19 +6831,52 @@ var DocxEditor = class _DocxEditor {
|
|
|
6453
6831
|
* behaviour this replaces. Null (no bridge support) keeps the previous offer-everything path.
|
|
6454
6832
|
*/
|
|
6455
6833
|
refreshBlockMoveTargets(source) {
|
|
6834
|
+
this.blockMoveTargets = source ? this.blockMoveTargetsFor(source) ?? null : null;
|
|
6835
|
+
}
|
|
6836
|
+
/**
|
|
6837
|
+
* This block's legal destinations, from the memo when it is there. Returns `undefined` — not
|
|
6838
|
+
* `null` — for "not asked yet", so a caller can tell an unknown answer from the engine's
|
|
6839
|
+
* "no bridge support, offer everything" one.
|
|
6840
|
+
*/
|
|
6841
|
+
blockMoveTargetsFor(source, options = {}) {
|
|
6456
6842
|
const bridge = this.exports.DocxSessionBridge;
|
|
6457
|
-
const sourceId =
|
|
6458
|
-
if (!sourceId || typeof bridge.ValidMoveTargets !== "function")
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6843
|
+
const sourceId = this.anchorIdOf(source);
|
|
6844
|
+
if (!sourceId || typeof bridge.ValidMoveTargets !== "function") return null;
|
|
6845
|
+
if (this.blockMoveTargetCache.has(sourceId)) return this.blockMoveTargetCache.get(sourceId);
|
|
6846
|
+
if (options.cachedOnly) return void 0;
|
|
6847
|
+
let targets;
|
|
6462
6848
|
try {
|
|
6463
|
-
const
|
|
6464
|
-
|
|
6465
|
-
targets.map((t) => [t.anchorId, { before: t.before, after: t.after }])
|
|
6466
|
-
);
|
|
6849
|
+
const parsed = JSON.parse(bridge.ValidMoveTargets(this.handle, sourceId));
|
|
6850
|
+
targets = new Map(parsed.map((t) => [t.anchorId, { before: t.before, after: t.after }]));
|
|
6467
6851
|
} catch {
|
|
6468
|
-
|
|
6852
|
+
targets = null;
|
|
6853
|
+
}
|
|
6854
|
+
this.blockMoveTargetCache.set(sourceId, targets);
|
|
6855
|
+
return targets;
|
|
6856
|
+
}
|
|
6857
|
+
/**
|
|
6858
|
+
* Ask for the hovered block's destinations off the interaction path, and hide the handle if
|
|
6859
|
+
* the answer comes back empty and that block is still the one under the pointer. The handle
|
|
6860
|
+
* therefore appears immediately on hover and withdraws a beat later on the rare immovable
|
|
6861
|
+
* block, instead of every hover paying for the query up front.
|
|
6862
|
+
*/
|
|
6863
|
+
prefetchBlockMoveTargets(source) {
|
|
6864
|
+
const view = this.container.ownerDocument.defaultView;
|
|
6865
|
+
if (!view) return;
|
|
6866
|
+
this.blockMoveTargetPrefetch?.();
|
|
6867
|
+
const run = () => {
|
|
6868
|
+
this.blockMoveTargetPrefetch = null;
|
|
6869
|
+
if (this.closed || !source.isConnected || this.blockDragSource !== source) return;
|
|
6870
|
+
if (this.blockMoveTargetsFor(source)?.size === 0 && this.blockDragHandle)
|
|
6871
|
+
this.blockDragHandle.style.display = "none";
|
|
6872
|
+
};
|
|
6873
|
+
const idle = view;
|
|
6874
|
+
if (idle.requestIdleCallback && idle.cancelIdleCallback) {
|
|
6875
|
+
const id = idle.requestIdleCallback(run, { timeout: 500 });
|
|
6876
|
+
this.blockMoveTargetPrefetch = () => idle.cancelIdleCallback(id);
|
|
6877
|
+
} else {
|
|
6878
|
+
const id = view.setTimeout(run, 0);
|
|
6879
|
+
this.blockMoveTargetPrefetch = () => view.clearTimeout(id);
|
|
6469
6880
|
}
|
|
6470
6881
|
}
|
|
6471
6882
|
/**
|
|
@@ -6480,45 +6891,75 @@ var DocxEditor = class _DocxEditor {
|
|
|
6480
6891
|
if (!sides) return false;
|
|
6481
6892
|
return position ? sides[position] : sides.before || sides.after;
|
|
6482
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
|
+
}
|
|
6483
6934
|
/**
|
|
6484
|
-
*
|
|
6485
|
-
*
|
|
6486
|
-
*
|
|
6487
|
-
*
|
|
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.
|
|
6488
6945
|
*/
|
|
6489
|
-
|
|
6490
|
-
const
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
const
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
this.blockDragTargetCleanup.push(dropTargetForElements({
|
|
6501
|
-
element: unit,
|
|
6502
|
-
// A target the engine would refuse is not a drop target at all, so Pragmatic never
|
|
6503
|
-
// fires onDragEnter for it and no indicator is drawn over it.
|
|
6504
|
-
canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE && source.data.sourceAnchorId !== this.anchorIdOf(unit) && this.isValidMoveTarget(unit),
|
|
6505
|
-
getData: ({ input }) => ({
|
|
6506
|
-
type: BLOCK_DRAG_TYPE,
|
|
6507
|
-
targetAnchorId: this.anchorIdOf(unit),
|
|
6508
|
-
position: this.dropPositionFor(unit, input.clientY),
|
|
6509
|
-
targetElement: unit
|
|
6510
|
-
}),
|
|
6511
|
-
onDragEnter: ({ self }) => {
|
|
6512
|
-
const pos = self.data.position === "after" ? "after" : "before";
|
|
6513
|
-
this.showDropIndicator(unit, pos);
|
|
6514
|
-
},
|
|
6515
|
-
onDrag: ({ self }) => {
|
|
6516
|
-
const pos = self.data.position === "after" ? "after" : "before";
|
|
6517
|
-
this.showDropIndicator(unit, pos);
|
|
6518
|
-
},
|
|
6519
|
-
onDragLeave: () => this.hideDropIndicator()
|
|
6520
|
-
}));
|
|
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;
|
|
6521
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;
|
|
6522
6963
|
}
|
|
6523
6964
|
closeBlockMoveMenu(restoreFocus = false) {
|
|
6524
6965
|
if (!this.blockMoveMenu || !this.blockDragHandle) return;
|
|
@@ -6555,7 +6996,8 @@ var DocxEditor = class _DocxEditor {
|
|
|
6555
6996
|
const index = units.indexOf(source);
|
|
6556
6997
|
if (index < 0) return null;
|
|
6557
6998
|
const position = action === "up" || action === "top" ? "before" : "after";
|
|
6558
|
-
const
|
|
6999
|
+
const side = position === "before" ? units.slice(0, index) : units.slice(index + 1);
|
|
7000
|
+
const candidates = side.filter((el) => this.isValidMoveTarget(el, position));
|
|
6559
7001
|
if (candidates.length === 0) return null;
|
|
6560
7002
|
if (action === "up") return { target: candidates[candidates.length - 1], position };
|
|
6561
7003
|
if (action === "down") return { target: candidates[0], position };
|
|
@@ -6692,20 +7134,50 @@ var DocxEditor = class _DocxEditor {
|
|
|
6692
7134
|
const source = this.currentBlockDragSource();
|
|
6693
7135
|
return { type: BLOCK_DRAG_TYPE, sourceAnchorId: source ? this.anchorIdOf(source) : void 0 };
|
|
6694
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
|
+
},
|
|
6695
7152
|
onDragStart: () => {
|
|
7153
|
+
const source = this.currentBlockDragSource();
|
|
6696
7154
|
this.blockDragging = true;
|
|
6697
7155
|
handle.classList.add("docx-block-dragging");
|
|
7156
|
+
source?.classList.add("docx-block-drag-source");
|
|
6698
7157
|
this.closeBlockMoveMenu();
|
|
6699
|
-
this.refreshBlockMoveTargets(
|
|
6700
|
-
this.
|
|
7158
|
+
this.refreshBlockMoveTargets(source);
|
|
7159
|
+
this.captureDropZones();
|
|
6701
7160
|
},
|
|
6702
7161
|
onDrop: () => {
|
|
6703
7162
|
this.blockDragging = false;
|
|
6704
7163
|
this.blockDragPointerDown = false;
|
|
7164
|
+
this.dropZones = [];
|
|
6705
7165
|
handle.classList.remove("docx-block-dragging");
|
|
7166
|
+
doc.querySelectorAll(".docx-block-drag-source").forEach((el) => el.classList.remove("docx-block-drag-source"));
|
|
6706
7167
|
this.hideDropIndicator();
|
|
6707
7168
|
}
|
|
6708
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
|
+
}));
|
|
6709
7181
|
this.blockDragCleanup.push(monitorForElements({
|
|
6710
7182
|
canMonitor: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
|
|
6711
7183
|
onDrop: ({ source, location: location2 }) => {
|
|
@@ -6732,10 +7204,13 @@ var DocxEditor = class _DocxEditor {
|
|
|
6732
7204
|
canScroll: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
|
|
6733
7205
|
getAllowedAxis: () => "vertical"
|
|
6734
7206
|
}));
|
|
6735
|
-
this.refreshBlockDropTargets();
|
|
6736
7207
|
}
|
|
6737
7208
|
teardownBlockDrag() {
|
|
6738
|
-
|
|
7209
|
+
this.blockMoveTargetPrefetch?.();
|
|
7210
|
+
this.blockMoveTargetPrefetch = null;
|
|
7211
|
+
this.blockMoveTargetCache.clear();
|
|
7212
|
+
this.dropZones = [];
|
|
7213
|
+
this.dropZoneScroller = null;
|
|
6739
7214
|
for (const cleanup of this.blockDragCleanup.splice(0)) cleanup();
|
|
6740
7215
|
this.blockDragHandle?.remove();
|
|
6741
7216
|
this.blockDropIndicator?.remove();
|
|
@@ -6824,17 +7299,17 @@ var DocxEditor = class _DocxEditor {
|
|
|
6824
7299
|
bodyRoot.after(this.region.footerBand);
|
|
6825
7300
|
this.region.refreshAll();
|
|
6826
7301
|
}
|
|
6827
|
-
/**
|
|
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
|
+
*/
|
|
6828
7310
|
mountHtml(fullHtml) {
|
|
6829
7311
|
const parsed = new DOMParser().parseFromString(fullHtml, "text/html");
|
|
6830
7312
|
const styles = Array.from(parsed.querySelectorAll("style")).map((s) => s.outerHTML).join("");
|
|
6831
|
-
if (!this.region) {
|
|
6832
|
-
this.container.innerHTML = styles + parsed.body.innerHTML;
|
|
6833
|
-
this.editRoot = this.container;
|
|
6834
|
-
if (this.options.editable) this.wireBlocks(this.container);
|
|
6835
|
-
this.stampPlanState();
|
|
6836
|
-
return;
|
|
6837
|
-
}
|
|
6838
7313
|
this.container.innerHTML = styles;
|
|
6839
7314
|
const flow = document.createElement("div");
|
|
6840
7315
|
flow.className = "docx-body-flow";
|
|
@@ -6843,7 +7318,8 @@ var DocxEditor = class _DocxEditor {
|
|
|
6843
7318
|
this.editRoot = flow;
|
|
6844
7319
|
if (this.options.editable) this.wireBlocks(flow);
|
|
6845
7320
|
this.stampPlanState();
|
|
6846
|
-
this.dockBands(flow);
|
|
7321
|
+
if (this.region) this.dockBands(flow);
|
|
7322
|
+
this.viewport.attach(flow, true);
|
|
6847
7323
|
}
|
|
6848
7324
|
/** Paginated mount: flow blocks into page boxes via pagination.ts, wire the page clones. */
|
|
6849
7325
|
mountPaginated(fullHtml) {
|
|
@@ -6864,6 +7340,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
6864
7340
|
this.editRoot = pageRoot;
|
|
6865
7341
|
if (this.options.editable) this.wireBlocks(pageRoot);
|
|
6866
7342
|
if (this.region) this.dockBands(target);
|
|
7343
|
+
this.viewport.attach(pageRoot, false);
|
|
6867
7344
|
}
|
|
6868
7345
|
wireBlocks(root) {
|
|
6869
7346
|
root.querySelectorAll("[data-anchor]").forEach((el) => this.wireBlock(el));
|
|
@@ -7252,11 +7729,22 @@ var DocxEditor = class _DocxEditor {
|
|
|
7252
7729
|
}
|
|
7253
7730
|
parseEdit(json) {
|
|
7254
7731
|
try {
|
|
7255
|
-
|
|
7732
|
+
const result = JSON.parse(json);
|
|
7733
|
+
if (result.success) this.invalidateBlockMoveTargets();
|
|
7734
|
+
return result;
|
|
7256
7735
|
} catch {
|
|
7257
7736
|
return { success: false };
|
|
7258
7737
|
}
|
|
7259
7738
|
}
|
|
7739
|
+
/**
|
|
7740
|
+
* Drop the memoized `ValidMoveTargets` answers. Which blocks a block may move next to is a
|
|
7741
|
+
* fact about the DOCUMENT, so it survives hovering but not editing — and the two places a
|
|
7742
|
+
* document changes are `parseEdit` (every mutation that returns an `EditResult`) and
|
|
7743
|
+
* undo/redo, which return a bare boolean and so cannot go through it.
|
|
7744
|
+
*/
|
|
7745
|
+
invalidateBlockMoveTargets() {
|
|
7746
|
+
this.blockMoveTargetCache.clear();
|
|
7747
|
+
}
|
|
7260
7748
|
// ─── M5: formatting commands (ribbon) ────────────────────────────────
|
|
7261
7749
|
// ─── Multi-block selection helpers (format a whole stack of paragraphs at once) ──────
|
|
7262
7750
|
/**
|
|
@@ -7810,12 +8298,16 @@ var DocxEditor = class _DocxEditor {
|
|
|
7810
8298
|
/** Undo the last edit (incremental repaint; falls back to a full re-render). */
|
|
7811
8299
|
undo() {
|
|
7812
8300
|
if (this.closed) return;
|
|
7813
|
-
if (this.exports.DocxSessionBridge.Undo(this.handle))
|
|
8301
|
+
if (!this.exports.DocxSessionBridge.Undo(this.handle)) return;
|
|
8302
|
+
this.invalidateBlockMoveTargets();
|
|
8303
|
+
this.reconcile();
|
|
7814
8304
|
}
|
|
7815
8305
|
/** Redo the last undone edit (incremental repaint; falls back to a full re-render). */
|
|
7816
8306
|
redo() {
|
|
7817
8307
|
if (this.closed) return;
|
|
7818
|
-
if (this.exports.DocxSessionBridge.Redo(this.handle))
|
|
8308
|
+
if (!this.exports.DocxSessionBridge.Redo(this.handle)) return;
|
|
8309
|
+
this.invalidateBlockMoveTargets();
|
|
8310
|
+
this.reconcile();
|
|
7819
8311
|
}
|
|
7820
8312
|
// ─── Header/footer region commands (no-ops unless `headerFooter` is on) ───────────────
|
|
7821
8313
|
/**
|
|
@@ -8044,7 +8536,11 @@ var DocxEditor = class _DocxEditor {
|
|
|
8044
8536
|
const oldTokens = oldNodes.map(_DocxEditor.domTokenOf);
|
|
8045
8537
|
const oldKinds = oldNodes.map(_DocxEditor.domKindOf);
|
|
8046
8538
|
const bodyDiff = diffUnits(oldTokens, plan.body);
|
|
8047
|
-
if (needsRemount(bodyDiff, plan.body, oldKinds))
|
|
8539
|
+
if (needsRemount(bodyDiff, plan.body, oldKinds)) {
|
|
8540
|
+
return this.bail(
|
|
8541
|
+
`needsRemount (li change or churn): +${bodyDiff.added.length} -${bodyDiff.removed.length} ~${bodyDiff.substituted.length} moved=${bodyDiff.moved.length} of ${plan.body.length}`
|
|
8542
|
+
);
|
|
8543
|
+
}
|
|
8048
8544
|
const fnState = this.notesDiff("footnotes", plan.footnotes);
|
|
8049
8545
|
const enState = this.notesDiff("endnotes", plan.endnotes);
|
|
8050
8546
|
if (fnState === null || enState === null) return this.bail("notes container unstampable/missing");
|
|
@@ -8653,14 +9149,7 @@ var RIBBON_CSS = `
|
|
|
8653
9149
|
SHOULD win.
|
|
8654
9150
|
(No backticks in this file's comments: the stylesheet is a template literal.) */
|
|
8655
9151
|
.dxr-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch; }
|
|
8656
|
-
.dxr[data-chrome] .dxr-surface {
|
|
8657
|
-
.dxr-surface[data-view="continuous"] > * { background: var(--dxr-sheet); }
|
|
8658
|
-
.dxr[data-chrome] .dxr-surface[data-view="continuous"] {
|
|
8659
|
-
padding: 56px 72px;
|
|
8660
|
-
border-radius: 3px;
|
|
8661
|
-
background: var(--dxr-sheet);
|
|
8662
|
-
box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
|
|
8663
|
-
}
|
|
9152
|
+
.dxr[data-chrome] .dxr-surface { margin: 26px auto; padding: 0 16px 96px; }
|
|
8664
9153
|
.dxr-surface [contenteditable="true"]:focus {
|
|
8665
9154
|
outline: 2px solid var(--dxr-accent);
|
|
8666
9155
|
outline-offset: 2px;
|
|
@@ -8672,7 +9161,10 @@ var RIBBON_CSS = `
|
|
|
8672
9161
|
so they dock as their own regions. Styled from the same tokens as the ribbon
|
|
8673
9162
|
so the surface reads as one instrument rather than two apps. */
|
|
8674
9163
|
.dxr-surface .docx-hf-band {
|
|
8675
|
-
|
|
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;
|
|
8676
9168
|
padding: 9px 72px 13px;
|
|
8677
9169
|
border: 1px solid var(--dxr-rule);
|
|
8678
9170
|
border-left: 2px solid #c2ccd9;
|
|
@@ -8680,7 +9172,7 @@ var RIBBON_CSS = `
|
|
|
8680
9172
|
background: var(--dxr-sheet);
|
|
8681
9173
|
}
|
|
8682
9174
|
.dxr-surface .docx-hf-band + .docx-body-flow { margin-top: 0; }
|
|
8683
|
-
.dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px
|
|
9175
|
+
.dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px auto 0; }
|
|
8684
9176
|
.dxr-surface .docx-hf-chrome {
|
|
8685
9177
|
display: flex;
|
|
8686
9178
|
gap: 8px;
|
|
@@ -8735,13 +9227,15 @@ var RIBBON_CSS = `
|
|
|
8735
9227
|
text-transform: none;
|
|
8736
9228
|
}
|
|
8737
9229
|
.dxr-surface .docx-hf-band[data-hf-inherited] { border-style: dashed; }
|
|
8738
|
-
.
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
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. */
|
|
8743
9235
|
.dxr[data-chrome] .dxr-surface[data-view="continuous"] .docx-body-flow {
|
|
8744
|
-
|
|
9236
|
+
max-width: 100%;
|
|
9237
|
+
margin: 0 auto;
|
|
9238
|
+
padding: 56px 0;
|
|
8745
9239
|
border-radius: 3px;
|
|
8746
9240
|
background: var(--dxr-sheet);
|
|
8747
9241
|
box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
|
|
@@ -8820,9 +9314,11 @@ var RIBBON_CSS = `
|
|
|
8820
9314
|
.dxr[data-chrome="compact"] .dxr-note { display: none; }
|
|
8821
9315
|
.dxr[data-chrome="compact"] .dxr-rail { display: none; }
|
|
8822
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. */
|
|
8823
9320
|
.dxr[data-chrome="compact"] .dxr-surface { margin: 12px auto; padding: 0 10px 64px; }
|
|
8824
|
-
.dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] { padding: 22px
|
|
8825
|
-
.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; }
|
|
8826
9322
|
.dxr[data-chrome="compact"] .dxr-surface .docx-hf-band { padding: 9px 18px 13px; }
|
|
8827
9323
|
.dxr[data-chrome="compact"] .dxr-surface .docx-hf-chrome,
|
|
8828
9324
|
.dxr[data-chrome="compact"] .dxr-surface .docx-hf-warning { margin-left: 0; }
|
|
@@ -9572,6 +10068,8 @@ var RibbonSurface = class {
|
|
|
9572
10068
|
fabricateClasses: this.options.fabricateClasses,
|
|
9573
10069
|
editable: this.options.editable,
|
|
9574
10070
|
scale: this.options.scale,
|
|
10071
|
+
columnWidth: this.options.columnWidth,
|
|
10072
|
+
fitToWidth: this.options.fitToWidth,
|
|
9575
10073
|
onEdit: this.options.onEdit,
|
|
9576
10074
|
onMove: this.options.onMove,
|
|
9577
10075
|
paginated,
|
|
@@ -11543,8 +12041,12 @@ export {
|
|
|
11543
12041
|
ComparisonLogLevel,
|
|
11544
12042
|
ConflictResolution,
|
|
11545
12043
|
ContextBoundary,
|
|
12044
|
+
DEFAULT_MARGIN,
|
|
12045
|
+
DEFAULT_PAGE_HEIGHT,
|
|
12046
|
+
DEFAULT_PAGE_WIDTH,
|
|
11546
12047
|
DiffFormat,
|
|
11547
12048
|
DocumentElementType,
|
|
12049
|
+
DocumentViewport,
|
|
11548
12050
|
DocxDiffFormatComparison,
|
|
11549
12051
|
DocxDiffRevisionGranularity,
|
|
11550
12052
|
DocxEditor,
|
|
@@ -11590,6 +12092,7 @@ export {
|
|
|
11590
12092
|
findElementsByType,
|
|
11591
12093
|
findMovePair,
|
|
11592
12094
|
findTextOccurrences,
|
|
12095
|
+
fitScale,
|
|
11593
12096
|
generateAnnotationCss,
|
|
11594
12097
|
generateAnnotationVisibilityCss,
|
|
11595
12098
|
getAnnotations,
|
|
@@ -11613,7 +12116,10 @@ export {
|
|
|
11613
12116
|
mountRibbon,
|
|
11614
12117
|
openDocxSession2 as openDocxSession,
|
|
11615
12118
|
paginateHtml,
|
|
12119
|
+
parseSectionDimensions,
|
|
11616
12120
|
projectAnnotationsOntoHtml,
|
|
12121
|
+
ptToPx,
|
|
12122
|
+
pxToPt,
|
|
11617
12123
|
removeAnnotation,
|
|
11618
12124
|
removeAnnotationFromHtml,
|
|
11619
12125
|
renderBlockHtml,
|