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.iife.js
CHANGED
|
@@ -132,8 +132,12 @@ var Docxodus = (() => {
|
|
|
132
132
|
ComparisonLogLevel: () => ComparisonLogLevel,
|
|
133
133
|
ConflictResolution: () => ConflictResolution,
|
|
134
134
|
ContextBoundary: () => ContextBoundary,
|
|
135
|
+
DEFAULT_MARGIN: () => DEFAULT_MARGIN,
|
|
136
|
+
DEFAULT_PAGE_HEIGHT: () => DEFAULT_PAGE_HEIGHT,
|
|
137
|
+
DEFAULT_PAGE_WIDTH: () => DEFAULT_PAGE_WIDTH,
|
|
135
138
|
DiffFormat: () => DiffFormat,
|
|
136
139
|
DocumentElementType: () => DocumentElementType,
|
|
140
|
+
DocumentViewport: () => DocumentViewport,
|
|
137
141
|
DocxDiffFormatComparison: () => DocxDiffFormatComparison,
|
|
138
142
|
DocxDiffRevisionGranularity: () => DocxDiffRevisionGranularity,
|
|
139
143
|
DocxEditor: () => DocxEditor,
|
|
@@ -179,6 +183,7 @@ var Docxodus = (() => {
|
|
|
179
183
|
findElementsByType: () => findElementsByType,
|
|
180
184
|
findMovePair: () => findMovePair,
|
|
181
185
|
findTextOccurrences: () => findTextOccurrences,
|
|
186
|
+
fitScale: () => fitScale,
|
|
182
187
|
generateAnnotationCss: () => generateAnnotationCss,
|
|
183
188
|
generateAnnotationVisibilityCss: () => generateAnnotationVisibilityCss,
|
|
184
189
|
getAnnotations: () => getAnnotations,
|
|
@@ -202,7 +207,10 @@ var Docxodus = (() => {
|
|
|
202
207
|
mountRibbon: () => mountRibbon,
|
|
203
208
|
openDocxSession: () => openDocxSession2,
|
|
204
209
|
paginateHtml: () => paginateHtml,
|
|
210
|
+
parseSectionDimensions: () => parseSectionDimensions,
|
|
205
211
|
projectAnnotationsOntoHtml: () => projectAnnotationsOntoHtml,
|
|
212
|
+
ptToPx: () => ptToPx,
|
|
213
|
+
pxToPt: () => pxToPt,
|
|
206
214
|
removeAnnotation: () => removeAnnotation,
|
|
207
215
|
removeAnnotationFromHtml: () => removeAnnotationFromHtml,
|
|
208
216
|
renderBlockHtml: () => renderBlockHtml,
|
|
@@ -601,7 +609,9 @@ var Docxodus = (() => {
|
|
|
601
609
|
* Table row/column editing, addressed by a cell-paragraph anchor (e.g. one returned from
|
|
602
610
|
* {@link insertTable}'s `created`). Insert clones the reference row/column's widths and starts
|
|
603
611
|
* empty (`created` lists the new cell-paragraph anchors); delete of the last row/column removes
|
|
604
|
-
* the whole table.
|
|
612
|
+
* the whole table. All four are grid-aware: inserting across a merge extends it, deleting
|
|
613
|
+
* through one narrows it, and deleting a vertical merge's lead row promotes the next row to
|
|
614
|
+
* carry it — the grid is never left ragged.
|
|
605
615
|
*/
|
|
606
616
|
insertTableRow(cellAnchorId, position) {
|
|
607
617
|
return JSON.parse(this.wasm.InsertTableRow(this.handle, cellAnchorId, position));
|
|
@@ -615,6 +625,28 @@ var Docxodus = (() => {
|
|
|
615
625
|
deleteTableColumn(cellAnchorId) {
|
|
616
626
|
return JSON.parse(this.wasm.DeleteTableColumn(this.handle, cellAnchorId));
|
|
617
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Merge the rectangle of cells anchored at `cellAnchorId` running `rowSpan` rows down ×
|
|
630
|
+
* `colSpan` cells right (Word's *Merge Cells*): `w:gridSpan` for the horizontal extent,
|
|
631
|
+
* `w:vMerge` restart/continue for the vertical one. The rectangle must tile the same whole grid
|
|
632
|
+
* columns in every row it covers and must not clip a vertical merge entering from above or
|
|
633
|
+
* continuing below — a partial overlap fails with `invalid_table_merge` instead of tearing the
|
|
634
|
+
* grid. `content` decides what happens to the absorbed cells' content (default `"append"`).
|
|
635
|
+
*/
|
|
636
|
+
mergeCells(cellAnchorId, rowSpan, colSpan, content = "append") {
|
|
637
|
+
return JSON.parse(
|
|
638
|
+
this.wasm.MergeCells(this.handle, cellAnchorId, rowSpan, colSpan, content)
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Split the merged cell at `cellAnchorId` back into unit cells, dropping its `w:gridSpan` and
|
|
643
|
+
* `w:vMerge` markup and restoring one cell per grid column (each taking its `w:tblGrid` width).
|
|
644
|
+
* Addressing a vertical-merge continuation unmerges the whole run. A cell with no merge markup
|
|
645
|
+
* fails with `invalid_table_merge`.
|
|
646
|
+
*/
|
|
647
|
+
unmergeCells(cellAnchorId) {
|
|
648
|
+
return JSON.parse(this.wasm.UnmergeCells(this.handle, cellAnchorId));
|
|
649
|
+
}
|
|
618
650
|
/**
|
|
619
651
|
* Table styling, addressed by a cell-paragraph anchor — the post-insert counterpart of
|
|
620
652
|
* {@link insertTable}'s options (issue #315 Stage A). `setColumnWidths` retunes `w:tblGrid` +
|
|
@@ -1414,20 +1446,18 @@ var Docxodus = (() => {
|
|
|
1414
1446
|
return (renderer ?? RENDERERS.decimal)(value);
|
|
1415
1447
|
}
|
|
1416
1448
|
|
|
1417
|
-
// src/
|
|
1449
|
+
// src/page-geometry.ts
|
|
1418
1450
|
var DEFAULT_PAGE_WIDTH = 612;
|
|
1419
1451
|
var DEFAULT_PAGE_HEIGHT = 792;
|
|
1420
1452
|
var DEFAULT_MARGIN = 72;
|
|
1421
|
-
var
|
|
1422
|
-
var MIN_BODY_CONTENT_HEIGHT = 72;
|
|
1453
|
+
var DEFAULT_HEADER_FOOTER_HEIGHT = 36;
|
|
1423
1454
|
function pxToPt(px) {
|
|
1424
1455
|
return px * 0.75;
|
|
1425
1456
|
}
|
|
1426
1457
|
function ptToPx(pt) {
|
|
1427
1458
|
return pt / 0.75;
|
|
1428
1459
|
}
|
|
1429
|
-
|
|
1430
|
-
function parseDimensions(section) {
|
|
1460
|
+
function parseSectionDimensions(section) {
|
|
1431
1461
|
const pageWidth = parseFloat(section.dataset.pageWidth || "") || DEFAULT_PAGE_WIDTH;
|
|
1432
1462
|
const pageHeight = parseFloat(section.dataset.pageHeight || "") || DEFAULT_PAGE_HEIGHT;
|
|
1433
1463
|
const contentWidth = parseFloat(section.dataset.contentWidth || "") || pageWidth - 2 * DEFAULT_MARGIN;
|
|
@@ -1451,6 +1481,42 @@ var Docxodus = (() => {
|
|
|
1451
1481
|
footerHeight
|
|
1452
1482
|
};
|
|
1453
1483
|
}
|
|
1484
|
+
function sectionWrappers(root) {
|
|
1485
|
+
const sections = Array.from(root.querySelectorAll("[data-section-index]"));
|
|
1486
|
+
return sections.length > 0 ? sections : [root];
|
|
1487
|
+
}
|
|
1488
|
+
var MIN_FIT_SCALE = 0.25;
|
|
1489
|
+
function fitScale(availablePx, naturalPt, max = 1) {
|
|
1490
|
+
if (!(availablePx > 0) || !(naturalPt > 0)) return max;
|
|
1491
|
+
const naturalPx = ptToPx(naturalPt);
|
|
1492
|
+
if (naturalPx <= availablePx) return max;
|
|
1493
|
+
return Math.max(MIN_FIT_SCALE, Math.min(max, availablePx / naturalPx));
|
|
1494
|
+
}
|
|
1495
|
+
function applyZoom(el, scale, naturalPt) {
|
|
1496
|
+
if (scale === 1) {
|
|
1497
|
+
el.style.removeProperty("zoom");
|
|
1498
|
+
el.style.removeProperty("transform");
|
|
1499
|
+
el.style.removeProperty("transform-origin");
|
|
1500
|
+
el.style.removeProperty("margin-right");
|
|
1501
|
+
el.style.removeProperty("margin-bottom");
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
const zoomSupported = typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("zoom", "0.5");
|
|
1505
|
+
if (zoomSupported) {
|
|
1506
|
+
el.style.zoom = String(scale);
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
el.style.transform = `scale(${scale})`;
|
|
1510
|
+
el.style.transformOrigin = "top left";
|
|
1511
|
+
if (naturalPt) {
|
|
1512
|
+
el.style.marginRight = `-${ptToPx(naturalPt.width * (1 - scale))}px`;
|
|
1513
|
+
el.style.marginBottom = `-${ptToPx(naturalPt.height * (1 - scale))}px`;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
// src/pagination.ts
|
|
1518
|
+
var MAX_FOOTNOTE_AREA_RATIO = 0.6;
|
|
1519
|
+
var MIN_BODY_CONTENT_HEIGHT = 72;
|
|
1454
1520
|
var PaginationEngine = class {
|
|
1455
1521
|
/**
|
|
1456
1522
|
* Creates a new pagination engine.
|
|
@@ -1496,7 +1562,7 @@ var Docxodus = (() => {
|
|
|
1496
1562
|
const sectionsToProcess = sections.length > 0 ? Array.from(sections) : [this.stagingElement];
|
|
1497
1563
|
for (const section of sectionsToProcess) {
|
|
1498
1564
|
const sectionIndex = parseInt(section.dataset.sectionIndex || "0", 10);
|
|
1499
|
-
const dims =
|
|
1565
|
+
const dims = parseSectionDimensions(section);
|
|
1500
1566
|
this.stagingElement.style.visibility = "hidden";
|
|
1501
1567
|
this.stagingElement.style.position = "absolute";
|
|
1502
1568
|
this.stagingElement.style.left = "-9999px";
|
|
@@ -2794,6 +2860,114 @@ var Docxodus = (() => {
|
|
|
2794
2860
|
return engine.paginate();
|
|
2795
2861
|
}
|
|
2796
2862
|
|
|
2863
|
+
// src/viewport.ts
|
|
2864
|
+
var DocumentViewport = class {
|
|
2865
|
+
constructor(host, options = {}) {
|
|
2866
|
+
this.root = null;
|
|
2867
|
+
/** Natural page size in points — the widest section's PAGE box, which is what must fit. */
|
|
2868
|
+
this.natural = { width: 0, height: 0 };
|
|
2869
|
+
this.observer = null;
|
|
2870
|
+
this.host = host;
|
|
2871
|
+
this.options = {
|
|
2872
|
+
columnWidth: options.columnWidth ?? "section",
|
|
2873
|
+
fitToWidth: options.fitToWidth ?? true,
|
|
2874
|
+
scale: options.scale ?? 1
|
|
2875
|
+
};
|
|
2876
|
+
}
|
|
2877
|
+
/**
|
|
2878
|
+
* Adopt a freshly mounted document root (a continuous flow, or the paginated page stack).
|
|
2879
|
+
* Safe to call on every remount; the previous root is released first.
|
|
2880
|
+
*
|
|
2881
|
+
* `applySectionGeometry` is false for the paginated view, which already builds real page
|
|
2882
|
+
* boxes at the section's dimensions — there the viewport contributes only the fit zoom.
|
|
2883
|
+
*/
|
|
2884
|
+
attach(root, applySectionGeometry) {
|
|
2885
|
+
this.release();
|
|
2886
|
+
this.root = root;
|
|
2887
|
+
this.natural = applySectionGeometry ? this.stampSections(root) : this.measurePages(root);
|
|
2888
|
+
this.refresh();
|
|
2889
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
2890
|
+
this.observer = new ResizeObserver(() => this.refresh());
|
|
2891
|
+
this.observer.observe(this.host);
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
/** Recompute the fit zoom against the host's current width. */
|
|
2895
|
+
refresh() {
|
|
2896
|
+
if (!this.root) return;
|
|
2897
|
+
const scale = this.scale;
|
|
2898
|
+
applyZoom(this.root, scale, this.natural);
|
|
2899
|
+
this.host.style.setProperty(
|
|
2900
|
+
"--docx-sheet-width",
|
|
2901
|
+
this.natural.width > 0 ? `${ptToPx(this.natural.width) * scale}px` : "100%"
|
|
2902
|
+
);
|
|
2903
|
+
}
|
|
2904
|
+
/** The zoom currently applied (1 = 100%). Reported by the ribbon's anchor rail. */
|
|
2905
|
+
get scale() {
|
|
2906
|
+
if (!this.root) return this.options.scale;
|
|
2907
|
+
return this.options.fitToWidth ? fitScale(this.availableWidthPx(), this.natural.width, this.options.scale) : this.options.scale;
|
|
2908
|
+
}
|
|
2909
|
+
dispose() {
|
|
2910
|
+
this.release();
|
|
2911
|
+
this.root = null;
|
|
2912
|
+
}
|
|
2913
|
+
release() {
|
|
2914
|
+
this.observer?.disconnect();
|
|
2915
|
+
this.observer = null;
|
|
2916
|
+
if (this.root) applyZoom(this.root, 1);
|
|
2917
|
+
this.host.style.removeProperty("--docx-sheet-width");
|
|
2918
|
+
}
|
|
2919
|
+
/** The host's content box, which is the space a page has to fit into. */
|
|
2920
|
+
availableWidthPx() {
|
|
2921
|
+
const style = typeof getComputedStyle === "function" ? getComputedStyle(this.host) : null;
|
|
2922
|
+
const padding = style ? (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0) : 0;
|
|
2923
|
+
return Math.max(0, this.host.clientWidth - padding);
|
|
2924
|
+
}
|
|
2925
|
+
/**
|
|
2926
|
+
* Give each section wrapper its `w:sectPr` geometry: the authored text column, guttered by
|
|
2927
|
+
* the authored margins. The wrapper then measures exactly one page wide, which is what the
|
|
2928
|
+
* sheet chrome paints and what the fit zoom scales.
|
|
2929
|
+
*/
|
|
2930
|
+
stampSections(root) {
|
|
2931
|
+
const sections = sectionWrappers(root);
|
|
2932
|
+
if (this.options.columnWidth === "fluid") {
|
|
2933
|
+
root.style.removeProperty("width");
|
|
2934
|
+
for (const section of sections) {
|
|
2935
|
+
section.style.removeProperty("width");
|
|
2936
|
+
section.style.removeProperty("padding-left");
|
|
2937
|
+
section.style.removeProperty("padding-right");
|
|
2938
|
+
}
|
|
2939
|
+
return { width: 0, height: 0 };
|
|
2940
|
+
}
|
|
2941
|
+
let widest = 0;
|
|
2942
|
+
for (const section of sections) {
|
|
2943
|
+
const dims = parseSectionDimensions(section);
|
|
2944
|
+
section.style.width = `${dims.contentWidth}pt`;
|
|
2945
|
+
section.style.paddingLeft = `${dims.marginLeft}pt`;
|
|
2946
|
+
section.style.paddingRight = `${dims.marginRight}pt`;
|
|
2947
|
+
section.style.boxSizing = "content-box";
|
|
2948
|
+
section.style.marginLeft = "auto";
|
|
2949
|
+
section.style.marginRight = "auto";
|
|
2950
|
+
widest = Math.max(widest, dims.pageWidth);
|
|
2951
|
+
}
|
|
2952
|
+
if (widest > 0 && sections[0] !== root) root.style.width = `${widest}pt`;
|
|
2953
|
+
return { width: widest, height: 0 };
|
|
2954
|
+
}
|
|
2955
|
+
/**
|
|
2956
|
+
* The paginated view's page boxes are already page-sized — `pagination.ts` writes each
|
|
2957
|
+
* box's `width` in points — so the widest of those is the natural width. Reading the
|
|
2958
|
+
* inline width rather than the laid-out box keeps this independent of the per-box zoom
|
|
2959
|
+
* pagination may itself have applied.
|
|
2960
|
+
*/
|
|
2961
|
+
measurePages(root) {
|
|
2962
|
+
let widest = 0;
|
|
2963
|
+
for (const box of Array.from(root.children)) {
|
|
2964
|
+
const declared = /^([\d.]+)pt$/.exec(box.style.width || "");
|
|
2965
|
+
widest = Math.max(widest, declared ? parseFloat(declared[1]) : pxToPt(box.offsetWidth));
|
|
2966
|
+
}
|
|
2967
|
+
return { width: widest, height: 0 };
|
|
2968
|
+
}
|
|
2969
|
+
};
|
|
2970
|
+
|
|
2797
2971
|
// src/editor-headerfooter.ts
|
|
2798
2972
|
var PAGE_FORMAT_LABELS = [
|
|
2799
2973
|
{ value: "", label: "Format\u2026" },
|
|
@@ -4882,6 +5056,146 @@ var Docxodus = (() => {
|
|
|
4882
5056
|
return once(cleanup);
|
|
4883
5057
|
}
|
|
4884
5058
|
|
|
5059
|
+
// node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js
|
|
5060
|
+
function ownKeys4(e, r) {
|
|
5061
|
+
var t = Object.keys(e);
|
|
5062
|
+
if (Object.getOwnPropertySymbols) {
|
|
5063
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
5064
|
+
r && (o = o.filter(function(r2) {
|
|
5065
|
+
return Object.getOwnPropertyDescriptor(e, r2).enumerable;
|
|
5066
|
+
})), t.push.apply(t, o);
|
|
5067
|
+
}
|
|
5068
|
+
return t;
|
|
5069
|
+
}
|
|
5070
|
+
function _objectSpread4(e) {
|
|
5071
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
5072
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
5073
|
+
r % 2 ? ownKeys4(Object(t), true).forEach(function(r2) {
|
|
5074
|
+
_defineProperty(e, r2, t[r2]);
|
|
5075
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys4(Object(t)).forEach(function(r2) {
|
|
5076
|
+
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
5077
|
+
});
|
|
5078
|
+
}
|
|
5079
|
+
return e;
|
|
5080
|
+
}
|
|
5081
|
+
function defaultOffset() {
|
|
5082
|
+
return {
|
|
5083
|
+
x: 0,
|
|
5084
|
+
y: 0
|
|
5085
|
+
};
|
|
5086
|
+
}
|
|
5087
|
+
function setCustomNativeDragPreview(_ref) {
|
|
5088
|
+
var render = _ref.render, nativeSetDragImage = _ref.nativeSetDragImage, _ref$getOffset = _ref.getOffset, getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
|
|
5089
|
+
var container = document.createElement("div");
|
|
5090
|
+
if (supportsPopover()) {
|
|
5091
|
+
container.setAttribute("popover", "manual");
|
|
5092
|
+
}
|
|
5093
|
+
Object.assign(container.style, _objectSpread4(_objectSpread4({
|
|
5094
|
+
// Ensuring we don't cause reflow when adding the element to the page
|
|
5095
|
+
// Using `position:fixed` rather than `position:absolute` so we are
|
|
5096
|
+
// positioned on the current viewport.
|
|
5097
|
+
// `position:fixed` also creates a new stacking context, so we don't need to do that here
|
|
5098
|
+
position: "fixed"
|
|
5099
|
+
}, supportsPopover() ? (
|
|
5100
|
+
// needs to come first as it has 'inset: unset' which
|
|
5101
|
+
// needs to be overridden by our top / left values
|
|
5102
|
+
popoverResetUserAgentStyles
|
|
5103
|
+
) : {
|
|
5104
|
+
// Fallback: using maximum possible z-index so that this element
|
|
5105
|
+
// will always be on top of other positioned content.
|
|
5106
|
+
zIndex: maxZIndex
|
|
5107
|
+
}), {}, {
|
|
5108
|
+
// According to `mdn`, the element can be offscreen:
|
|
5109
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
|
|
5110
|
+
//
|
|
5111
|
+
// However, that information does not appear in the specs:
|
|
5112
|
+
// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-setdragimage-dev
|
|
5113
|
+
//
|
|
5114
|
+
// If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
|
|
5115
|
+
top: 0,
|
|
5116
|
+
left: 0,
|
|
5117
|
+
// Avoiding any additional events caused by the new element (being super safe)
|
|
5118
|
+
pointerEvents: "none"
|
|
5119
|
+
}));
|
|
5120
|
+
document.body.append(container);
|
|
5121
|
+
if (supportsPopover()) {
|
|
5122
|
+
container.showPopover();
|
|
5123
|
+
}
|
|
5124
|
+
var unmount = render({
|
|
5125
|
+
container
|
|
5126
|
+
});
|
|
5127
|
+
queueMicrotask(function() {
|
|
5128
|
+
var previewOffset = getOffset({
|
|
5129
|
+
container
|
|
5130
|
+
});
|
|
5131
|
+
if (isSafari()) {
|
|
5132
|
+
var rect = container.getBoundingClientRect();
|
|
5133
|
+
if (rect.width === 0) {
|
|
5134
|
+
return;
|
|
5135
|
+
}
|
|
5136
|
+
container.style.left = "-".concat(rect.width - 1e-4, "px");
|
|
5137
|
+
}
|
|
5138
|
+
nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
5139
|
+
});
|
|
5140
|
+
function cleanup() {
|
|
5141
|
+
unbindMonitor();
|
|
5142
|
+
unmount === null || unmount === void 0 || unmount();
|
|
5143
|
+
document.body.removeChild(container);
|
|
5144
|
+
}
|
|
5145
|
+
var unbindMonitor = monitorForElements({
|
|
5146
|
+
// Remove portal in the dragstart event so that the user will never see it
|
|
5147
|
+
onDragStart: cleanup,
|
|
5148
|
+
// Backup: remove portal when the drop finishes (this would be an error case)
|
|
5149
|
+
onDrop: cleanup
|
|
5150
|
+
});
|
|
5151
|
+
}
|
|
5152
|
+
|
|
5153
|
+
// node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/is-safari-on-ios.js
|
|
5154
|
+
var isSafariOnIOS = once(function isSafariOnIOS2() {
|
|
5155
|
+
if (false) {
|
|
5156
|
+
return false;
|
|
5157
|
+
}
|
|
5158
|
+
return isSafari() && "ontouchend" in document;
|
|
5159
|
+
});
|
|
5160
|
+
|
|
5161
|
+
// node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/center-under-pointer.js
|
|
5162
|
+
var centerUnderPointer = function centerUnderPointer2(_ref) {
|
|
5163
|
+
var container = _ref.container;
|
|
5164
|
+
var rect = container.getBoundingClientRect();
|
|
5165
|
+
return {
|
|
5166
|
+
x: rect.width / 2,
|
|
5167
|
+
y: rect.height / 2
|
|
5168
|
+
};
|
|
5169
|
+
};
|
|
5170
|
+
|
|
5171
|
+
// node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/pointer-outside-of-preview.js
|
|
5172
|
+
function pointerOutsideOfPreview(point) {
|
|
5173
|
+
return function getOffset(_ref) {
|
|
5174
|
+
var container = _ref.container;
|
|
5175
|
+
if (isSafariOnIOS() || isAndroid()) {
|
|
5176
|
+
return centerUnderPointer({
|
|
5177
|
+
container
|
|
5178
|
+
});
|
|
5179
|
+
}
|
|
5180
|
+
Object.assign(container.style, {
|
|
5181
|
+
borderInlineStart: "".concat(point.x, " solid transparent"),
|
|
5182
|
+
borderTop: "".concat(point.y, " solid transparent")
|
|
5183
|
+
});
|
|
5184
|
+
var computed = window.getComputedStyle(container);
|
|
5185
|
+
if (computed.direction === "rtl") {
|
|
5186
|
+
var box = container.getBoundingClientRect();
|
|
5187
|
+
return {
|
|
5188
|
+
x: box.width,
|
|
5189
|
+
y: 0
|
|
5190
|
+
};
|
|
5191
|
+
}
|
|
5192
|
+
return {
|
|
5193
|
+
x: 0,
|
|
5194
|
+
y: 0
|
|
5195
|
+
};
|
|
5196
|
+
};
|
|
5197
|
+
}
|
|
5198
|
+
|
|
4885
5199
|
// node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/engagement-history.js
|
|
4886
5200
|
var ledger2 = /* @__PURE__ */ new Map();
|
|
4887
5201
|
var requested = /* @__PURE__ */ new Set();
|
|
@@ -5015,7 +5329,7 @@ var Docxodus = (() => {
|
|
|
5015
5329
|
}
|
|
5016
5330
|
|
|
5017
5331
|
// node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/configuration.js
|
|
5018
|
-
function
|
|
5332
|
+
function ownKeys5(e, r) {
|
|
5019
5333
|
var t = Object.keys(e);
|
|
5020
5334
|
if (Object.getOwnPropertySymbols) {
|
|
5021
5335
|
var o = Object.getOwnPropertySymbols(e);
|
|
@@ -5025,12 +5339,12 @@ var Docxodus = (() => {
|
|
|
5025
5339
|
}
|
|
5026
5340
|
return t;
|
|
5027
5341
|
}
|
|
5028
|
-
function
|
|
5342
|
+
function _objectSpread5(e) {
|
|
5029
5343
|
for (var r = 1; r < arguments.length; r++) {
|
|
5030
5344
|
var t = null != arguments[r] ? arguments[r] : {};
|
|
5031
|
-
r % 2 ?
|
|
5345
|
+
r % 2 ? ownKeys5(Object(t), true).forEach(function(r2) {
|
|
5032
5346
|
_defineProperty(e, r2, t[r2]);
|
|
5033
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) :
|
|
5347
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys5(Object(t)).forEach(function(r2) {
|
|
5034
5348
|
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
5035
5349
|
});
|
|
5036
5350
|
}
|
|
@@ -5065,7 +5379,7 @@ var Docxodus = (() => {
|
|
|
5065
5379
|
};
|
|
5066
5380
|
function getInternalConfig(provided) {
|
|
5067
5381
|
var _provided$maxScrollSp;
|
|
5068
|
-
return
|
|
5382
|
+
return _objectSpread5(_objectSpread5({}, baseConfig), {}, {
|
|
5069
5383
|
// only allowing limited control over the config at this stage
|
|
5070
5384
|
maxPixelScrollPerSecond: maxPixelScrollPerSecond[(_provided$maxScrollSp = provided === null || provided === void 0 ? void 0 : provided.maxScrollSpeed) !== null && _provided$maxScrollSp !== void 0 ? _provided$maxScrollSp : "standard"]
|
|
5071
5385
|
});
|
|
@@ -5549,7 +5863,7 @@ var Docxodus = (() => {
|
|
|
5549
5863
|
}
|
|
5550
5864
|
|
|
5551
5865
|
// node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/make-api.js
|
|
5552
|
-
function
|
|
5866
|
+
function ownKeys6(e, r) {
|
|
5553
5867
|
var t = Object.keys(e);
|
|
5554
5868
|
if (Object.getOwnPropertySymbols) {
|
|
5555
5869
|
var o = Object.getOwnPropertySymbols(e);
|
|
@@ -5559,12 +5873,12 @@ var Docxodus = (() => {
|
|
|
5559
5873
|
}
|
|
5560
5874
|
return t;
|
|
5561
5875
|
}
|
|
5562
|
-
function
|
|
5876
|
+
function _objectSpread6(e) {
|
|
5563
5877
|
for (var r = 1; r < arguments.length; r++) {
|
|
5564
5878
|
var t = null != arguments[r] ? arguments[r] : {};
|
|
5565
|
-
r % 2 ?
|
|
5879
|
+
r % 2 ? ownKeys6(Object(t), true).forEach(function(r2) {
|
|
5566
5880
|
_defineProperty(e, r2, t[r2]);
|
|
5567
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) :
|
|
5881
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys6(Object(t)).forEach(function(r2) {
|
|
5568
5882
|
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
5569
5883
|
});
|
|
5570
5884
|
}
|
|
@@ -5603,7 +5917,7 @@ var Docxodus = (() => {
|
|
|
5603
5917
|
}
|
|
5604
5918
|
function autoScrollWindow() {
|
|
5605
5919
|
var args = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
5606
|
-
var unique =
|
|
5920
|
+
var unique = _objectSpread6({}, args);
|
|
5607
5921
|
windowRegistry.add(unique);
|
|
5608
5922
|
function cleanup() {
|
|
5609
5923
|
windowRegistry.delete(unique);
|
|
@@ -5756,6 +6070,11 @@ var Docxodus = (() => {
|
|
|
5756
6070
|
var EDITABLE_TAGS = /* @__PURE__ */ new Set(["P", "H1", "H2", "H3", "H4", "H5", "H6"]);
|
|
5757
6071
|
var BLOCK_DRAG_TYPE = "docxodus-block";
|
|
5758
6072
|
var blockDragStyledDocuments = /* @__PURE__ */ new WeakSet();
|
|
6073
|
+
function blockPreviewText(unit) {
|
|
6074
|
+
if (unit.tagName === "TABLE") return "Table";
|
|
6075
|
+
const text = (unit.textContent ?? "").trim().replace(/\s+/g, " ");
|
|
6076
|
+
return text.length > 48 ? `${text.slice(0, 48)}\u2026` : text;
|
|
6077
|
+
}
|
|
5759
6078
|
function ensureBlockDragStyles(doc) {
|
|
5760
6079
|
if (blockDragStyledDocuments.has(doc)) return;
|
|
5761
6080
|
blockDragStyledDocuments.add(doc);
|
|
@@ -5770,10 +6089,28 @@ var Docxodus = (() => {
|
|
|
5770
6089
|
}
|
|
5771
6090
|
.docx-block-handle:hover, .docx-block-handle:focus-visible { color: #344054; border-color: #98a2b3; outline: none; }
|
|
5772
6091
|
.docx-block-handle[aria-pressed="true"] { color: #175cd3; border-color: #84adff; background: #eff8ff; }
|
|
5773
|
-
.docx-block-handle.docx-block-dragging { cursor: grabbing; opacity: .
|
|
6092
|
+
.docx-block-handle.docx-block-dragging { cursor: grabbing; opacity: .35; }
|
|
6093
|
+
/* The block being carried. Dimming it is the "a drag is happening" signal that survives the
|
|
6094
|
+
pointer being anywhere on screen \u2014 the drop line only says where, not what. */
|
|
6095
|
+
.docx-block-drag-source { opacity: .38; transition: opacity 120ms ease-out; }
|
|
6096
|
+
/* Positioned by transform so tracking the pointer costs no layout. Flipping display none\u2192block
|
|
6097
|
+
restarts the fade \u2014 one cheap entry animation per appearance, none while it tracks. */
|
|
5774
6098
|
.docx-block-drop-indicator {
|
|
5775
|
-
position: fixed; z-index: 2147482999; display: none; height:
|
|
5776
|
-
|
|
6099
|
+
position: fixed; top: 0; left: 0; z-index: 2147482999; display: none; height: 0;
|
|
6100
|
+
pointer-events: none; border-top: 2px solid #2e90fa;
|
|
6101
|
+
filter: drop-shadow(0 1px 2px rgba(46,144,250,.5));
|
|
6102
|
+
animation: docx-block-drop-in 110ms ease-out;
|
|
6103
|
+
}
|
|
6104
|
+
.docx-block-drop-indicator::before {
|
|
6105
|
+
content: ""; position: absolute; top: -5px; left: -2px; width: 8px; height: 8px;
|
|
6106
|
+
border-radius: 50%; background: #2e90fa;
|
|
6107
|
+
}
|
|
6108
|
+
@keyframes docx-block-drop-in { from { opacity: 0; } to { opacity: 1; } }
|
|
6109
|
+
.docx-block-drag-preview {
|
|
6110
|
+
max-width: 320px; padding: 6px 10px; border: 1px solid #b2ddff; border-radius: 6px;
|
|
6111
|
+
background: #eff8ff; color: #175cd3; box-shadow: 0 6px 16px rgba(16,24,40,.18);
|
|
6112
|
+
font: 500 13px/1.35 system-ui, sans-serif; white-space: nowrap; overflow: hidden;
|
|
6113
|
+
text-overflow: ellipsis;
|
|
5777
6114
|
}
|
|
5778
6115
|
.docx-block-move-menu {
|
|
5779
6116
|
position: fixed; z-index: 2147483001; display: none; min-width: 150px; padding: 5px;
|
|
@@ -6161,12 +6498,22 @@ var Docxodus = (() => {
|
|
|
6161
6498
|
this.blockMoveLive = null;
|
|
6162
6499
|
this.blockDragSource = null;
|
|
6163
6500
|
this.blockDragCleanup = [];
|
|
6164
|
-
|
|
6501
|
+
/** Block boxes measured at drag start — see `BlockDropZone`. Empty when no drag is in flight. */
|
|
6502
|
+
this.dropZones = [];
|
|
6503
|
+
/** Combined scroll offset when `dropZones` was measured, and the scroller measured against. */
|
|
6504
|
+
this.dropZoneOrigin = 0;
|
|
6505
|
+
this.dropZoneScroller = null;
|
|
6165
6506
|
this.blockDragging = false;
|
|
6166
6507
|
this.blockDragPointerDown = false;
|
|
6167
6508
|
/** Anchors the current drag source may legally move next to, per the engine's own rules.
|
|
6168
6509
|
* Null when the bridge predates ValidMoveTargets — then every block is offered, as before. */
|
|
6169
6510
|
this.blockMoveTargets = null;
|
|
6511
|
+
/** Memoized `ValidMoveTargets` answers, keyed by source anchor and dropped whenever an edit
|
|
6512
|
+
* lands. The legal-target set is a property of the document, so hovering back and forth over
|
|
6513
|
+
* the same blocks between edits must not re-ask the engine. */
|
|
6514
|
+
this.blockMoveTargetCache = /* @__PURE__ */ new Map();
|
|
6515
|
+
/** Cancels the pending idle prefetch of the hovered block's targets — see `showBlockHandle`. */
|
|
6516
|
+
this.blockMoveTargetPrefetch = null;
|
|
6170
6517
|
/** Why the last move was refused, verbatim from the engine — diagnostics, not announcement copy. */
|
|
6171
6518
|
this.lastMoveError = null;
|
|
6172
6519
|
/**
|
|
@@ -6284,6 +6631,11 @@ var Docxodus = (() => {
|
|
|
6284
6631
|
this.handle = handle;
|
|
6285
6632
|
this.options = options;
|
|
6286
6633
|
this.editRoot = container;
|
|
6634
|
+
this.viewport = new DocumentViewport(container, {
|
|
6635
|
+
columnWidth: options.columnWidth,
|
|
6636
|
+
fitToWidth: options.fitToWidth,
|
|
6637
|
+
scale: options.scale
|
|
6638
|
+
});
|
|
6287
6639
|
if (typeof document !== "undefined") {
|
|
6288
6640
|
document.addEventListener("selectionchange", this.onSelectionChange);
|
|
6289
6641
|
document.addEventListener("mousedown", this.onMouseDown, true);
|
|
@@ -6366,6 +6718,8 @@ var Docxodus = (() => {
|
|
|
6366
6718
|
editable: options.editable ?? true,
|
|
6367
6719
|
paginated: options.paginated ?? false,
|
|
6368
6720
|
scale: options.scale ?? 1,
|
|
6721
|
+
columnWidth: options.columnWidth ?? "section",
|
|
6722
|
+
fitToWidth: options.fitToWidth ?? true,
|
|
6369
6723
|
headerFooter: options.headerFooter ?? false,
|
|
6370
6724
|
blockDrag: options.blockDrag ?? false,
|
|
6371
6725
|
trackedChanges: options.trackedChanges ?? 0 /* Accept */,
|
|
@@ -6422,6 +6776,7 @@ var Docxodus = (() => {
|
|
|
6422
6776
|
}
|
|
6423
6777
|
this.clearDragSelection();
|
|
6424
6778
|
this.teardownBlockDrag();
|
|
6779
|
+
this.viewport.dispose();
|
|
6425
6780
|
this.exports.DocxSessionBridge.CloseSession(this.handle);
|
|
6426
6781
|
}
|
|
6427
6782
|
/**
|
|
@@ -6439,6 +6794,14 @@ var Docxodus = (() => {
|
|
|
6439
6794
|
get root() {
|
|
6440
6795
|
return this.container;
|
|
6441
6796
|
}
|
|
6797
|
+
/**
|
|
6798
|
+
* The zoom the viewport is currently applying (1 = 100%). Below 1 the page is wider than the
|
|
6799
|
+
* host and has been scaled to fit rather than reflowed — the honest thing to show a user who
|
|
6800
|
+
* is wondering why a phone shows the whole page.
|
|
6801
|
+
*/
|
|
6802
|
+
get zoom() {
|
|
6803
|
+
return this.viewport.scale;
|
|
6804
|
+
}
|
|
6442
6805
|
/**
|
|
6443
6806
|
* The live `DocxSession` handle backing this editor — the model of record.
|
|
6444
6807
|
*
|
|
@@ -6467,8 +6830,7 @@ var Docxodus = (() => {
|
|
|
6467
6830
|
return true;
|
|
6468
6831
|
}
|
|
6469
6832
|
const destination = res.created?.[0] ?? res.modified?.[0];
|
|
6470
|
-
|
|
6471
|
-
else this.reconcile();
|
|
6833
|
+
this.reconcile();
|
|
6472
6834
|
const moved = destination ? this.bodyUnitNodes().find((el) => el.getAttribute("data-anchor") === destination.unid) : null;
|
|
6473
6835
|
if (moved) {
|
|
6474
6836
|
moved.classList.add("docx-block-move-flash");
|
|
@@ -6493,7 +6855,12 @@ var Docxodus = (() => {
|
|
|
6493
6855
|
const node = target instanceof Node ? target : null;
|
|
6494
6856
|
const el = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
|
|
6495
6857
|
if (!el || !this.editRoot.contains(el)) return null;
|
|
6496
|
-
|
|
6858
|
+
let unit = null;
|
|
6859
|
+
for (let candidate = el.closest("[data-anchor]"); candidate && this.editRoot.contains(candidate); candidate = candidate.parentElement?.closest("[data-anchor]") ?? null) {
|
|
6860
|
+
unit = candidate;
|
|
6861
|
+
}
|
|
6862
|
+
if (!unit || unit.closest("section.footnotes, section.endnotes")) return null;
|
|
6863
|
+
return unit;
|
|
6497
6864
|
}
|
|
6498
6865
|
isMovableBlockUnit(unit) {
|
|
6499
6866
|
if (!unit || !this.anchorIdOf(unit)) return false;
|
|
@@ -6515,18 +6882,18 @@ var Docxodus = (() => {
|
|
|
6515
6882
|
if (!handle || !this.isMovableBlockUnit(unit)) return;
|
|
6516
6883
|
const changed = unit !== this.blockDragSource;
|
|
6517
6884
|
this.blockDragSource = unit;
|
|
6518
|
-
|
|
6519
|
-
if (
|
|
6885
|
+
const known = this.blockMoveTargetsFor(unit, { cachedOnly: true });
|
|
6886
|
+
if (known?.size === 0) {
|
|
6520
6887
|
handle.style.display = "none";
|
|
6521
6888
|
return;
|
|
6522
6889
|
}
|
|
6890
|
+
if (changed && known === void 0) this.prefetchBlockMoveTargets(unit);
|
|
6523
6891
|
const rect = unit.getBoundingClientRect();
|
|
6524
6892
|
handle.style.display = "flex";
|
|
6525
6893
|
handle.style.left = `${Math.max(4, rect.left - 32)}px`;
|
|
6526
6894
|
handle.style.top = `${Math.max(4, rect.top + (unit.tagName === "TABLE" ? 6 : Math.max(0, (rect.height - 28) / 2)))}px`;
|
|
6527
|
-
const preview = (unit
|
|
6895
|
+
const preview = blockPreviewText(unit);
|
|
6528
6896
|
handle.setAttribute("aria-label", preview ? `Move block: ${preview}` : "Move block");
|
|
6529
|
-
if (changed) this.refreshBlockDropTargets();
|
|
6530
6897
|
}
|
|
6531
6898
|
hideBlockHandle() {
|
|
6532
6899
|
if (this.blockDragging || this.blockMoveMenu?.style.display === "block") return;
|
|
@@ -6536,14 +6903,33 @@ var Docxodus = (() => {
|
|
|
6536
6903
|
const source = this.currentBlockDragSource();
|
|
6537
6904
|
if (source && this.blockDragHandle?.style.display !== "none") this.showBlockHandle(source);
|
|
6538
6905
|
}
|
|
6539
|
-
|
|
6906
|
+
/** Draw the drop line on `zone`'s requested edge, or take it away when there is no target. */
|
|
6907
|
+
paintDropIndicator(data) {
|
|
6540
6908
|
const indicator = this.blockDropIndicator;
|
|
6909
|
+
const zone = data.zone;
|
|
6541
6910
|
if (!indicator) return;
|
|
6542
|
-
|
|
6911
|
+
if (!zone) {
|
|
6912
|
+
this.hideDropIndicator();
|
|
6913
|
+
return;
|
|
6914
|
+
}
|
|
6915
|
+
const y = Math.round(this.dropEdgeY(zone, data.position === "after" ? "after" : "before") + this.dropZoneShift()) - 1;
|
|
6916
|
+
indicator.style.transform = `translate3d(${Math.round(zone.left)}px, ${y}px, 0)`;
|
|
6917
|
+
indicator.style.width = `${Math.max(24, Math.round(zone.width))}px`;
|
|
6543
6918
|
indicator.style.display = "block";
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6919
|
+
}
|
|
6920
|
+
/**
|
|
6921
|
+
* Where to draw the line for an insertion on `position` of `zone` — the MIDDLE of the gap to
|
|
6922
|
+
* the neighbour on that side, not the zone's own border-box edge. A paragraph's `w:spacing`
|
|
6923
|
+
* becomes a CSS margin, which sits outside the box, so drawing on the edge underlines the
|
|
6924
|
+
* block's last line instead of reading as a gap between two blocks. Falls back to the raw edge
|
|
6925
|
+
* at the ends of the flow, and degrades to the same value when blocks are contiguous.
|
|
6926
|
+
*/
|
|
6927
|
+
dropEdgeY(zone, position) {
|
|
6928
|
+
const neighbour = this.dropZones[zone.index + (position === "after" ? 1 : -1)];
|
|
6929
|
+
if (!neighbour) {
|
|
6930
|
+
return position === "after" ? zone.bottom + zone.marginAfter / 2 : zone.top - zone.marginBefore / 2;
|
|
6931
|
+
}
|
|
6932
|
+
return position === "after" ? (zone.bottom + neighbour.top) / 2 : (neighbour.bottom + zone.top) / 2;
|
|
6547
6933
|
}
|
|
6548
6934
|
hideDropIndicator() {
|
|
6549
6935
|
if (this.blockDropIndicator) this.blockDropIndicator.style.display = "none";
|
|
@@ -6563,19 +6949,52 @@ var Docxodus = (() => {
|
|
|
6563
6949
|
* behaviour this replaces. Null (no bridge support) keeps the previous offer-everything path.
|
|
6564
6950
|
*/
|
|
6565
6951
|
refreshBlockMoveTargets(source) {
|
|
6952
|
+
this.blockMoveTargets = source ? this.blockMoveTargetsFor(source) ?? null : null;
|
|
6953
|
+
}
|
|
6954
|
+
/**
|
|
6955
|
+
* This block's legal destinations, from the memo when it is there. Returns `undefined` — not
|
|
6956
|
+
* `null` — for "not asked yet", so a caller can tell an unknown answer from the engine's
|
|
6957
|
+
* "no bridge support, offer everything" one.
|
|
6958
|
+
*/
|
|
6959
|
+
blockMoveTargetsFor(source, options = {}) {
|
|
6566
6960
|
const bridge = this.exports.DocxSessionBridge;
|
|
6567
|
-
const sourceId =
|
|
6568
|
-
if (!sourceId || typeof bridge.ValidMoveTargets !== "function")
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6961
|
+
const sourceId = this.anchorIdOf(source);
|
|
6962
|
+
if (!sourceId || typeof bridge.ValidMoveTargets !== "function") return null;
|
|
6963
|
+
if (this.blockMoveTargetCache.has(sourceId)) return this.blockMoveTargetCache.get(sourceId);
|
|
6964
|
+
if (options.cachedOnly) return void 0;
|
|
6965
|
+
let targets;
|
|
6572
6966
|
try {
|
|
6573
|
-
const
|
|
6574
|
-
|
|
6575
|
-
targets.map((t) => [t.anchorId, { before: t.before, after: t.after }])
|
|
6576
|
-
);
|
|
6967
|
+
const parsed = JSON.parse(bridge.ValidMoveTargets(this.handle, sourceId));
|
|
6968
|
+
targets = new Map(parsed.map((t) => [t.anchorId, { before: t.before, after: t.after }]));
|
|
6577
6969
|
} catch {
|
|
6578
|
-
|
|
6970
|
+
targets = null;
|
|
6971
|
+
}
|
|
6972
|
+
this.blockMoveTargetCache.set(sourceId, targets);
|
|
6973
|
+
return targets;
|
|
6974
|
+
}
|
|
6975
|
+
/**
|
|
6976
|
+
* Ask for the hovered block's destinations off the interaction path, and hide the handle if
|
|
6977
|
+
* the answer comes back empty and that block is still the one under the pointer. The handle
|
|
6978
|
+
* therefore appears immediately on hover and withdraws a beat later on the rare immovable
|
|
6979
|
+
* block, instead of every hover paying for the query up front.
|
|
6980
|
+
*/
|
|
6981
|
+
prefetchBlockMoveTargets(source) {
|
|
6982
|
+
const view = this.container.ownerDocument.defaultView;
|
|
6983
|
+
if (!view) return;
|
|
6984
|
+
this.blockMoveTargetPrefetch?.();
|
|
6985
|
+
const run = () => {
|
|
6986
|
+
this.blockMoveTargetPrefetch = null;
|
|
6987
|
+
if (this.closed || !source.isConnected || this.blockDragSource !== source) return;
|
|
6988
|
+
if (this.blockMoveTargetsFor(source)?.size === 0 && this.blockDragHandle)
|
|
6989
|
+
this.blockDragHandle.style.display = "none";
|
|
6990
|
+
};
|
|
6991
|
+
const idle = view;
|
|
6992
|
+
if (idle.requestIdleCallback && idle.cancelIdleCallback) {
|
|
6993
|
+
const id = idle.requestIdleCallback(run, { timeout: 500 });
|
|
6994
|
+
this.blockMoveTargetPrefetch = () => idle.cancelIdleCallback(id);
|
|
6995
|
+
} else {
|
|
6996
|
+
const id = view.setTimeout(run, 0);
|
|
6997
|
+
this.blockMoveTargetPrefetch = () => view.clearTimeout(id);
|
|
6579
6998
|
}
|
|
6580
6999
|
}
|
|
6581
7000
|
/**
|
|
@@ -6590,45 +7009,75 @@ var Docxodus = (() => {
|
|
|
6590
7009
|
if (!sides) return false;
|
|
6591
7010
|
return position ? sides[position] : sides.before || sides.after;
|
|
6592
7011
|
}
|
|
7012
|
+
/** Measure every movable block once, at drag start. See `BlockDropZone`. */
|
|
7013
|
+
captureDropZones() {
|
|
7014
|
+
const view = this.container.ownerDocument.defaultView;
|
|
7015
|
+
this.dropZoneScroller = this.scrollContainer();
|
|
7016
|
+
this.dropZoneOrigin = this.scrollOffsetSum();
|
|
7017
|
+
this.dropZones = [];
|
|
7018
|
+
const boxes = [];
|
|
7019
|
+
for (const unit of this.bodyUnitNodes()) {
|
|
7020
|
+
const anchorId = this.isMovableBlockUnit(unit) ? this.anchorIdOf(unit) : null;
|
|
7021
|
+
if (!anchorId) continue;
|
|
7022
|
+
const box = this.unitWrapperOf(unit);
|
|
7023
|
+
const rect = box.getBoundingClientRect();
|
|
7024
|
+
boxes.push(box);
|
|
7025
|
+
this.dropZones.push({
|
|
7026
|
+
unit,
|
|
7027
|
+
anchorId,
|
|
7028
|
+
index: this.dropZones.length,
|
|
7029
|
+
top: rect.top,
|
|
7030
|
+
bottom: rect.bottom,
|
|
7031
|
+
left: rect.left,
|
|
7032
|
+
width: rect.width,
|
|
7033
|
+
marginBefore: 0,
|
|
7034
|
+
marginAfter: 0
|
|
7035
|
+
});
|
|
7036
|
+
}
|
|
7037
|
+
const ends = new Set([0, this.dropZones.length - 1].filter((i) => i >= 0 && i < boxes.length));
|
|
7038
|
+
for (const i of ends) {
|
|
7039
|
+
const style = view?.getComputedStyle(boxes[i]);
|
|
7040
|
+
this.dropZones[i].marginBefore = parseFloat(style?.marginTop ?? "0") || 0;
|
|
7041
|
+
this.dropZones[i].marginAfter = parseFloat(style?.marginBottom ?? "0") || 0;
|
|
7042
|
+
}
|
|
7043
|
+
}
|
|
7044
|
+
scrollOffsetSum() {
|
|
7045
|
+
const view = this.container.ownerDocument.defaultView;
|
|
7046
|
+
return (view?.scrollY ?? 0) + (this.dropZoneScroller?.scrollTop ?? 0);
|
|
7047
|
+
}
|
|
7048
|
+
/** How far the measured boxes have travelled since capture, from scrolling (drag autoscroll). */
|
|
7049
|
+
dropZoneShift() {
|
|
7050
|
+
return this.dropZoneOrigin - this.scrollOffsetSum();
|
|
7051
|
+
}
|
|
6593
7052
|
/**
|
|
6594
|
-
*
|
|
6595
|
-
*
|
|
6596
|
-
*
|
|
6597
|
-
*
|
|
7053
|
+
* Where a drop at `clientY` lands, or null when nothing there is legal.
|
|
7054
|
+
*
|
|
7055
|
+
* Resolution is by VERTICAL GEOMETRY over the measured blocks, not by which element the pointer
|
|
7056
|
+
* is over: the drag handle floats in the page margin, so a drag straight down the gutter — the
|
|
7057
|
+
* natural gesture — never crosses a paragraph box, and element hit testing gave those drags no
|
|
7058
|
+
* indicator and no drop at all. The nearest block by vertical distance is the target; the half
|
|
7059
|
+
* the pointer is in picks the side, snapped to the other side when only that one is legal
|
|
7060
|
+
* (a section break or a cross-block range usually makes exactly one side illegal). When neither
|
|
7061
|
+
* side is legal — the pointer is in a region this block cannot reach — there is no drop, and
|
|
7062
|
+
* nothing is drawn.
|
|
6598
7063
|
*/
|
|
6599
|
-
|
|
6600
|
-
const
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
const
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
this.blockDragTargetCleanup.push(dropTargetForElements({
|
|
6611
|
-
element: unit,
|
|
6612
|
-
// A target the engine would refuse is not a drop target at all, so Pragmatic never
|
|
6613
|
-
// fires onDragEnter for it and no indicator is drawn over it.
|
|
6614
|
-
canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE && source.data.sourceAnchorId !== this.anchorIdOf(unit) && this.isValidMoveTarget(unit),
|
|
6615
|
-
getData: ({ input }) => ({
|
|
6616
|
-
type: BLOCK_DRAG_TYPE,
|
|
6617
|
-
targetAnchorId: this.anchorIdOf(unit),
|
|
6618
|
-
position: this.dropPositionFor(unit, input.clientY),
|
|
6619
|
-
targetElement: unit
|
|
6620
|
-
}),
|
|
6621
|
-
onDragEnter: ({ self }) => {
|
|
6622
|
-
const pos = self.data.position === "after" ? "after" : "before";
|
|
6623
|
-
this.showDropIndicator(unit, pos);
|
|
6624
|
-
},
|
|
6625
|
-
onDrag: ({ self }) => {
|
|
6626
|
-
const pos = self.data.position === "after" ? "after" : "before";
|
|
6627
|
-
this.showDropIndicator(unit, pos);
|
|
6628
|
-
},
|
|
6629
|
-
onDragLeave: () => this.hideDropIndicator()
|
|
6630
|
-
}));
|
|
7064
|
+
resolveDropAt(clientY) {
|
|
7065
|
+
const y = clientY - this.dropZoneShift();
|
|
7066
|
+
let best = null;
|
|
7067
|
+
let bestGap = Infinity;
|
|
7068
|
+
for (const zone of this.dropZones) {
|
|
7069
|
+
const gap = y < zone.top ? zone.top - y : y > zone.bottom ? y - zone.bottom : 0;
|
|
7070
|
+
if (gap < bestGap) {
|
|
7071
|
+
best = zone;
|
|
7072
|
+
bestGap = gap;
|
|
7073
|
+
}
|
|
7074
|
+
if (gap === 0) break;
|
|
6631
7075
|
}
|
|
7076
|
+
if (!best || best.unit === this.blockDragSource) return null;
|
|
7077
|
+
const preferred = y < (best.top + best.bottom) / 2 ? "before" : "after";
|
|
7078
|
+
if (this.isValidMoveTarget(best.unit, preferred)) return { zone: best, position: preferred };
|
|
7079
|
+
const other = preferred === "before" ? "after" : "before";
|
|
7080
|
+
return this.isValidMoveTarget(best.unit, other) ? { zone: best, position: other } : null;
|
|
6632
7081
|
}
|
|
6633
7082
|
closeBlockMoveMenu(restoreFocus = false) {
|
|
6634
7083
|
if (!this.blockMoveMenu || !this.blockDragHandle) return;
|
|
@@ -6665,7 +7114,8 @@ var Docxodus = (() => {
|
|
|
6665
7114
|
const index = units.indexOf(source);
|
|
6666
7115
|
if (index < 0) return null;
|
|
6667
7116
|
const position = action === "up" || action === "top" ? "before" : "after";
|
|
6668
|
-
const
|
|
7117
|
+
const side = position === "before" ? units.slice(0, index) : units.slice(index + 1);
|
|
7118
|
+
const candidates = side.filter((el) => this.isValidMoveTarget(el, position));
|
|
6669
7119
|
if (candidates.length === 0) return null;
|
|
6670
7120
|
if (action === "up") return { target: candidates[candidates.length - 1], position };
|
|
6671
7121
|
if (action === "down") return { target: candidates[0], position };
|
|
@@ -6802,20 +7252,50 @@ var Docxodus = (() => {
|
|
|
6802
7252
|
const source = this.currentBlockDragSource();
|
|
6803
7253
|
return { type: BLOCK_DRAG_TYPE, sourceAnchorId: source ? this.anchorIdOf(source) : void 0 };
|
|
6804
7254
|
},
|
|
7255
|
+
// The browser would otherwise ghost the 26px grip, which says nothing about what is moving.
|
|
7256
|
+
onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
7257
|
+
const source = this.currentBlockDragSource();
|
|
7258
|
+
setCustomNativeDragPreview({
|
|
7259
|
+
nativeSetDragImage,
|
|
7260
|
+
getOffset: pointerOutsideOfPreview({ x: "14px", y: "10px" }),
|
|
7261
|
+
render: ({ container }) => {
|
|
7262
|
+
const chip = doc.createElement("div");
|
|
7263
|
+
chip.className = "docx-block-drag-preview";
|
|
7264
|
+
chip.textContent = source && blockPreviewText(source) || "Move block";
|
|
7265
|
+
container.appendChild(chip);
|
|
7266
|
+
return () => chip.remove();
|
|
7267
|
+
}
|
|
7268
|
+
});
|
|
7269
|
+
},
|
|
6805
7270
|
onDragStart: () => {
|
|
7271
|
+
const source = this.currentBlockDragSource();
|
|
6806
7272
|
this.blockDragging = true;
|
|
6807
7273
|
handle.classList.add("docx-block-dragging");
|
|
7274
|
+
source?.classList.add("docx-block-drag-source");
|
|
6808
7275
|
this.closeBlockMoveMenu();
|
|
6809
|
-
this.refreshBlockMoveTargets(
|
|
6810
|
-
this.
|
|
7276
|
+
this.refreshBlockMoveTargets(source);
|
|
7277
|
+
this.captureDropZones();
|
|
6811
7278
|
},
|
|
6812
7279
|
onDrop: () => {
|
|
6813
7280
|
this.blockDragging = false;
|
|
6814
7281
|
this.blockDragPointerDown = false;
|
|
7282
|
+
this.dropZones = [];
|
|
6815
7283
|
handle.classList.remove("docx-block-dragging");
|
|
7284
|
+
doc.querySelectorAll(".docx-block-drag-source").forEach((el) => el.classList.remove("docx-block-drag-source"));
|
|
6816
7285
|
this.hideDropIndicator();
|
|
6817
7286
|
}
|
|
6818
7287
|
}));
|
|
7288
|
+
this.blockDragCleanup.push(dropTargetForElements({
|
|
7289
|
+
element: this.editRoot,
|
|
7290
|
+
canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
|
|
7291
|
+
getData: ({ input }) => {
|
|
7292
|
+
const hit = this.resolveDropAt(input.clientY);
|
|
7293
|
+
return hit ? { type: BLOCK_DRAG_TYPE, targetAnchorId: hit.zone.anchorId, position: hit.position, zone: hit.zone } : { type: BLOCK_DRAG_TYPE };
|
|
7294
|
+
},
|
|
7295
|
+
onDragEnter: ({ self }) => this.paintDropIndicator(self.data),
|
|
7296
|
+
onDrag: ({ self }) => this.paintDropIndicator(self.data),
|
|
7297
|
+
onDragLeave: () => this.hideDropIndicator()
|
|
7298
|
+
}));
|
|
6819
7299
|
this.blockDragCleanup.push(monitorForElements({
|
|
6820
7300
|
canMonitor: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
|
|
6821
7301
|
onDrop: ({ source, location: location2 }) => {
|
|
@@ -6842,10 +7322,13 @@ var Docxodus = (() => {
|
|
|
6842
7322
|
canScroll: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,
|
|
6843
7323
|
getAllowedAxis: () => "vertical"
|
|
6844
7324
|
}));
|
|
6845
|
-
this.refreshBlockDropTargets();
|
|
6846
7325
|
}
|
|
6847
7326
|
teardownBlockDrag() {
|
|
6848
|
-
|
|
7327
|
+
this.blockMoveTargetPrefetch?.();
|
|
7328
|
+
this.blockMoveTargetPrefetch = null;
|
|
7329
|
+
this.blockMoveTargetCache.clear();
|
|
7330
|
+
this.dropZones = [];
|
|
7331
|
+
this.dropZoneScroller = null;
|
|
6849
7332
|
for (const cleanup of this.blockDragCleanup.splice(0)) cleanup();
|
|
6850
7333
|
this.blockDragHandle?.remove();
|
|
6851
7334
|
this.blockDropIndicator?.remove();
|
|
@@ -6934,17 +7417,17 @@ var Docxodus = (() => {
|
|
|
6934
7417
|
bodyRoot.after(this.region.footerBand);
|
|
6935
7418
|
this.region.refreshAll();
|
|
6936
7419
|
}
|
|
6937
|
-
/**
|
|
7420
|
+
/**
|
|
7421
|
+
* Continuous (non-paginated) mount: inject the converter's styles + body, wire blocks.
|
|
7422
|
+
*
|
|
7423
|
+
* The body always gets its own `.docx-body-flow` wrapper — not only when bands are docked.
|
|
7424
|
+
* It is the sheet: the element the viewport gives page geometry to and zooms, and the one
|
|
7425
|
+
* the bands dock around. Without it the container would have to be both the scrolling host
|
|
7426
|
+
* and the scaled page, which are different boxes.
|
|
7427
|
+
*/
|
|
6938
7428
|
mountHtml(fullHtml) {
|
|
6939
7429
|
const parsed = new DOMParser().parseFromString(fullHtml, "text/html");
|
|
6940
7430
|
const styles = Array.from(parsed.querySelectorAll("style")).map((s) => s.outerHTML).join("");
|
|
6941
|
-
if (!this.region) {
|
|
6942
|
-
this.container.innerHTML = styles + parsed.body.innerHTML;
|
|
6943
|
-
this.editRoot = this.container;
|
|
6944
|
-
if (this.options.editable) this.wireBlocks(this.container);
|
|
6945
|
-
this.stampPlanState();
|
|
6946
|
-
return;
|
|
6947
|
-
}
|
|
6948
7431
|
this.container.innerHTML = styles;
|
|
6949
7432
|
const flow = document.createElement("div");
|
|
6950
7433
|
flow.className = "docx-body-flow";
|
|
@@ -6953,7 +7436,8 @@ var Docxodus = (() => {
|
|
|
6953
7436
|
this.editRoot = flow;
|
|
6954
7437
|
if (this.options.editable) this.wireBlocks(flow);
|
|
6955
7438
|
this.stampPlanState();
|
|
6956
|
-
this.dockBands(flow);
|
|
7439
|
+
if (this.region) this.dockBands(flow);
|
|
7440
|
+
this.viewport.attach(flow, true);
|
|
6957
7441
|
}
|
|
6958
7442
|
/** Paginated mount: flow blocks into page boxes via pagination.ts, wire the page clones. */
|
|
6959
7443
|
mountPaginated(fullHtml) {
|
|
@@ -6974,6 +7458,7 @@ var Docxodus = (() => {
|
|
|
6974
7458
|
this.editRoot = pageRoot;
|
|
6975
7459
|
if (this.options.editable) this.wireBlocks(pageRoot);
|
|
6976
7460
|
if (this.region) this.dockBands(target);
|
|
7461
|
+
this.viewport.attach(pageRoot, false);
|
|
6977
7462
|
}
|
|
6978
7463
|
wireBlocks(root) {
|
|
6979
7464
|
root.querySelectorAll("[data-anchor]").forEach((el) => this.wireBlock(el));
|
|
@@ -7362,11 +7847,22 @@ var Docxodus = (() => {
|
|
|
7362
7847
|
}
|
|
7363
7848
|
parseEdit(json) {
|
|
7364
7849
|
try {
|
|
7365
|
-
|
|
7850
|
+
const result = JSON.parse(json);
|
|
7851
|
+
if (result.success) this.invalidateBlockMoveTargets();
|
|
7852
|
+
return result;
|
|
7366
7853
|
} catch {
|
|
7367
7854
|
return { success: false };
|
|
7368
7855
|
}
|
|
7369
7856
|
}
|
|
7857
|
+
/**
|
|
7858
|
+
* Drop the memoized `ValidMoveTargets` answers. Which blocks a block may move next to is a
|
|
7859
|
+
* fact about the DOCUMENT, so it survives hovering but not editing — and the two places a
|
|
7860
|
+
* document changes are `parseEdit` (every mutation that returns an `EditResult`) and
|
|
7861
|
+
* undo/redo, which return a bare boolean and so cannot go through it.
|
|
7862
|
+
*/
|
|
7863
|
+
invalidateBlockMoveTargets() {
|
|
7864
|
+
this.blockMoveTargetCache.clear();
|
|
7865
|
+
}
|
|
7370
7866
|
// ─── M5: formatting commands (ribbon) ────────────────────────────────
|
|
7371
7867
|
// ─── Multi-block selection helpers (format a whole stack of paragraphs at once) ──────
|
|
7372
7868
|
/**
|
|
@@ -7920,12 +8416,16 @@ var Docxodus = (() => {
|
|
|
7920
8416
|
/** Undo the last edit (incremental repaint; falls back to a full re-render). */
|
|
7921
8417
|
undo() {
|
|
7922
8418
|
if (this.closed) return;
|
|
7923
|
-
if (this.exports.DocxSessionBridge.Undo(this.handle))
|
|
8419
|
+
if (!this.exports.DocxSessionBridge.Undo(this.handle)) return;
|
|
8420
|
+
this.invalidateBlockMoveTargets();
|
|
8421
|
+
this.reconcile();
|
|
7924
8422
|
}
|
|
7925
8423
|
/** Redo the last undone edit (incremental repaint; falls back to a full re-render). */
|
|
7926
8424
|
redo() {
|
|
7927
8425
|
if (this.closed) return;
|
|
7928
|
-
if (this.exports.DocxSessionBridge.Redo(this.handle))
|
|
8426
|
+
if (!this.exports.DocxSessionBridge.Redo(this.handle)) return;
|
|
8427
|
+
this.invalidateBlockMoveTargets();
|
|
8428
|
+
this.reconcile();
|
|
7929
8429
|
}
|
|
7930
8430
|
// ─── Header/footer region commands (no-ops unless `headerFooter` is on) ───────────────
|
|
7931
8431
|
/**
|
|
@@ -8154,7 +8654,11 @@ var Docxodus = (() => {
|
|
|
8154
8654
|
const oldTokens = oldNodes.map(_DocxEditor.domTokenOf);
|
|
8155
8655
|
const oldKinds = oldNodes.map(_DocxEditor.domKindOf);
|
|
8156
8656
|
const bodyDiff = diffUnits(oldTokens, plan.body);
|
|
8157
|
-
if (needsRemount(bodyDiff, plan.body, oldKinds))
|
|
8657
|
+
if (needsRemount(bodyDiff, plan.body, oldKinds)) {
|
|
8658
|
+
return this.bail(
|
|
8659
|
+
`needsRemount (li change or churn): +${bodyDiff.added.length} -${bodyDiff.removed.length} ~${bodyDiff.substituted.length} moved=${bodyDiff.moved.length} of ${plan.body.length}`
|
|
8660
|
+
);
|
|
8661
|
+
}
|
|
8158
8662
|
const fnState = this.notesDiff("footnotes", plan.footnotes);
|
|
8159
8663
|
const enState = this.notesDiff("endnotes", plan.endnotes);
|
|
8160
8664
|
if (fnState === null || enState === null) return this.bail("notes container unstampable/missing");
|
|
@@ -8763,14 +9267,7 @@ var Docxodus = (() => {
|
|
|
8763
9267
|
SHOULD win.
|
|
8764
9268
|
(No backticks in this file's comments: the stylesheet is a template literal.) */
|
|
8765
9269
|
.dxr-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch; }
|
|
8766
|
-
.dxr[data-chrome] .dxr-surface {
|
|
8767
|
-
.dxr-surface[data-view="continuous"] > * { background: var(--dxr-sheet); }
|
|
8768
|
-
.dxr[data-chrome] .dxr-surface[data-view="continuous"] {
|
|
8769
|
-
padding: 56px 72px;
|
|
8770
|
-
border-radius: 3px;
|
|
8771
|
-
background: var(--dxr-sheet);
|
|
8772
|
-
box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
|
|
8773
|
-
}
|
|
9270
|
+
.dxr[data-chrome] .dxr-surface { margin: 26px auto; padding: 0 16px 96px; }
|
|
8774
9271
|
.dxr-surface [contenteditable="true"]:focus {
|
|
8775
9272
|
outline: 2px solid var(--dxr-accent);
|
|
8776
9273
|
outline-offset: 2px;
|
|
@@ -8782,7 +9279,10 @@ var Docxodus = (() => {
|
|
|
8782
9279
|
so they dock as their own regions. Styled from the same tokens as the ribbon
|
|
8783
9280
|
so the surface reads as one instrument rather than two apps. */
|
|
8784
9281
|
.dxr-surface .docx-hf-band {
|
|
8785
|
-
|
|
9282
|
+
/* Docked outside the zoomed sheet, so it takes the page's on-screen width from the
|
|
9283
|
+
custom property the viewport publishes rather than stretching to the whole surface. */
|
|
9284
|
+
width: min(100%, var(--docx-sheet-width, 100%));
|
|
9285
|
+
margin: 0 auto 14px;
|
|
8786
9286
|
padding: 9px 72px 13px;
|
|
8787
9287
|
border: 1px solid var(--dxr-rule);
|
|
8788
9288
|
border-left: 2px solid #c2ccd9;
|
|
@@ -8790,7 +9290,7 @@ var Docxodus = (() => {
|
|
|
8790
9290
|
background: var(--dxr-sheet);
|
|
8791
9291
|
}
|
|
8792
9292
|
.dxr-surface .docx-hf-band + .docx-body-flow { margin-top: 0; }
|
|
8793
|
-
.dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px
|
|
9293
|
+
.dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px auto 0; }
|
|
8794
9294
|
.dxr-surface .docx-hf-chrome {
|
|
8795
9295
|
display: flex;
|
|
8796
9296
|
gap: 8px;
|
|
@@ -8845,13 +9345,15 @@ var Docxodus = (() => {
|
|
|
8845
9345
|
text-transform: none;
|
|
8846
9346
|
}
|
|
8847
9347
|
.dxr-surface .docx-hf-band[data-hf-inherited] { border-style: dashed; }
|
|
8848
|
-
.
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
9348
|
+
/* The sheet IS the page. The editor's viewport sizes .docx-body-flow to the section's page
|
|
9349
|
+
width and its section wrappers to the authored text column, so the horizontal gutters here
|
|
9350
|
+
are the document's own w:sectPr margins, not a padding this chrome invents; only the
|
|
9351
|
+
vertical breathing room is ours. Centering is left to margin:auto so a page the viewport
|
|
9352
|
+
has zoomed to fit stays centered at its scaled width. */
|
|
8853
9353
|
.dxr[data-chrome] .dxr-surface[data-view="continuous"] .docx-body-flow {
|
|
8854
|
-
|
|
9354
|
+
max-width: 100%;
|
|
9355
|
+
margin: 0 auto;
|
|
9356
|
+
padding: 56px 0;
|
|
8855
9357
|
border-radius: 3px;
|
|
8856
9358
|
background: var(--dxr-sheet);
|
|
8857
9359
|
box-shadow: 0 1px 3px rgba(16, 20, 24, .14), 0 8px 24px rgba(16, 20, 24, .05);
|
|
@@ -8930,9 +9432,11 @@ var Docxodus = (() => {
|
|
|
8930
9432
|
.dxr[data-chrome="compact"] .dxr-note { display: none; }
|
|
8931
9433
|
.dxr[data-chrome="compact"] .dxr-rail { display: none; }
|
|
8932
9434
|
.dxr[data-chrome="compact"] .dxr-hint { display: none; }
|
|
9435
|
+
/* Compact trims the chrome around the page, never the page: the document's own column width
|
|
9436
|
+
is what the viewport's fit-to-width zoom scales, so a phone shows a whole smaller page
|
|
9437
|
+
instead of a narrower one that breaks its lines somewhere Word never would. */
|
|
8933
9438
|
.dxr[data-chrome="compact"] .dxr-surface { margin: 12px auto; padding: 0 10px 64px; }
|
|
8934
|
-
.dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] { padding: 22px
|
|
8935
|
-
.dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] .docx-body-flow { padding: 22px 18px; }
|
|
9439
|
+
.dxr[data-chrome="compact"] .dxr-surface[data-view="continuous"] .docx-body-flow { padding: 22px 0; }
|
|
8936
9440
|
.dxr[data-chrome="compact"] .dxr-surface .docx-hf-band { padding: 9px 18px 13px; }
|
|
8937
9441
|
.dxr[data-chrome="compact"] .dxr-surface .docx-hf-chrome,
|
|
8938
9442
|
.dxr[data-chrome="compact"] .dxr-surface .docx-hf-warning { margin-left: 0; }
|
|
@@ -9682,6 +10186,8 @@ var Docxodus = (() => {
|
|
|
9682
10186
|
fabricateClasses: this.options.fabricateClasses,
|
|
9683
10187
|
editable: this.options.editable,
|
|
9684
10188
|
scale: this.options.scale,
|
|
10189
|
+
columnWidth: this.options.columnWidth,
|
|
10190
|
+
fitToWidth: this.options.fitToWidth,
|
|
9685
10191
|
onEdit: this.options.onEdit,
|
|
9686
10192
|
onMove: this.options.onMove,
|
|
9687
10193
|
paginated,
|