docxodus 9.6.0 → 9.8.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/LICENSE +22 -0
- package/README.md +0 -1
- package/dist/editor.bundle.js +462 -173
- package/dist/editor.d.ts +4 -4
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +55 -8
- package/dist/editor.js.map +1 -1
- package/dist/embed.bundle.js +466 -174
- package/dist/embed.d.ts.map +1 -1
- package/dist/embed.iife.js +465 -173
- package/dist/embed.js +3 -0
- package/dist/embed.js.map +1 -1
- package/dist/page-geometry.d.ts +50 -3
- package/dist/page-geometry.d.ts.map +1 -1
- package/dist/page-geometry.js +63 -6
- package/dist/page-geometry.js.map +1 -1
- package/dist/pagination.bundle.js +253 -68
- package/dist/pagination.d.ts +33 -8
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +198 -78
- package/dist/pagination.js.map +1 -1
- package/dist/ribbon-chrome.d.ts +2 -2
- package/dist/ribbon-chrome.d.ts.map +1 -1
- package/dist/ribbon-chrome.js +171 -97
- package/dist/ribbon-chrome.js.map +1 -1
- package/dist/ribbon.d.ts +8 -0
- package/dist/ribbon.d.ts.map +1 -1
- package/dist/ribbon.js +1 -0
- package/dist/ribbon.js.map +1 -1
- 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.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Linq.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 +6 -6
- 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 +13 -5
- package/dist/wasm/index.html +0 -238
- package/dist/wasm/main.js +0 -26
package/dist/embed.bundle.js
CHANGED
|
@@ -1332,7 +1332,7 @@ function formatPageNumber(value, format) {
|
|
|
1332
1332
|
var DEFAULT_PAGE_WIDTH = 612;
|
|
1333
1333
|
var DEFAULT_PAGE_HEIGHT = 792;
|
|
1334
1334
|
var DEFAULT_MARGIN = 72;
|
|
1335
|
-
var
|
|
1335
|
+
var DEFAULT_HEADER_FOOTER_DISTANCE = 36;
|
|
1336
1336
|
function pxToPt(px) {
|
|
1337
1337
|
return px * 0.75;
|
|
1338
1338
|
}
|
|
@@ -1348,8 +1348,8 @@ function parseSectionDimensions(section) {
|
|
|
1348
1348
|
const marginRight = parseFloat(section.dataset.marginRight || "") || DEFAULT_MARGIN;
|
|
1349
1349
|
const marginBottom = parseFloat(section.dataset.marginBottom || "") || DEFAULT_MARGIN;
|
|
1350
1350
|
const marginLeft = parseFloat(section.dataset.marginLeft || "") || DEFAULT_MARGIN;
|
|
1351
|
-
const
|
|
1352
|
-
const
|
|
1351
|
+
const headerDistance = parseFloat(section.dataset.headerHeight || "") || DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
1352
|
+
const footerDistance = parseFloat(section.dataset.footerHeight || "") || DEFAULT_HEADER_FOOTER_DISTANCE;
|
|
1353
1353
|
return {
|
|
1354
1354
|
pageWidth,
|
|
1355
1355
|
pageHeight,
|
|
@@ -1359,8 +1359,37 @@ function parseSectionDimensions(section) {
|
|
|
1359
1359
|
marginRight,
|
|
1360
1360
|
marginBottom,
|
|
1361
1361
|
marginLeft,
|
|
1362
|
-
|
|
1363
|
-
|
|
1362
|
+
headerDistance,
|
|
1363
|
+
footerDistance,
|
|
1364
|
+
headerHeight: headerDistance,
|
|
1365
|
+
footerHeight: footerDistance
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
var MIN_BODY_BAND_PT = 12;
|
|
1369
|
+
function resolvePageBands(dims, headerContentHeight, footerContentHeight) {
|
|
1370
|
+
const headerTop = dims.headerDistance;
|
|
1371
|
+
const footerBottom = dims.pageHeight - dims.footerDistance;
|
|
1372
|
+
const headerReach = headerContentHeight > 0 ? headerTop + headerContentHeight : 0;
|
|
1373
|
+
const footerReach = footerContentHeight > 0 ? footerBottom - footerContentHeight : dims.pageHeight;
|
|
1374
|
+
let bodyTop = Math.max(dims.marginTop, headerReach);
|
|
1375
|
+
let bodyBottom = Math.min(dims.pageHeight - dims.marginBottom, footerReach);
|
|
1376
|
+
const shortfall = MIN_BODY_BAND_PT - (bodyBottom - bodyTop);
|
|
1377
|
+
if (shortfall > 0) {
|
|
1378
|
+
const headerGrowth = bodyTop - dims.marginTop;
|
|
1379
|
+
const footerGrowth = dims.pageHeight - dims.marginBottom - bodyBottom;
|
|
1380
|
+
const growth = headerGrowth + footerGrowth;
|
|
1381
|
+
if (growth > 0) {
|
|
1382
|
+
bodyTop -= shortfall * headerGrowth / growth;
|
|
1383
|
+
bodyBottom += shortfall * footerGrowth / growth;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
return {
|
|
1387
|
+
headerTop,
|
|
1388
|
+
headerHeight: Math.max(0, Math.min(headerContentHeight, bodyTop - headerTop)),
|
|
1389
|
+
bodyTop,
|
|
1390
|
+
bodyHeight: Math.max(0, bodyBottom - bodyTop),
|
|
1391
|
+
footerTop: footerBottom - Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom)),
|
|
1392
|
+
footerHeight: Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom))
|
|
1364
1393
|
};
|
|
1365
1394
|
}
|
|
1366
1395
|
function sectionWrappers(root) {
|
|
@@ -1637,9 +1666,9 @@ var PaginationEngine = class {
|
|
|
1637
1666
|
*/
|
|
1638
1667
|
smallestEffectiveContentHeight(dims, sectionIndex) {
|
|
1639
1668
|
return Math.min(
|
|
1640
|
-
this.
|
|
1641
|
-
this.
|
|
1642
|
-
this.
|
|
1669
|
+
this.getPageBands(dims, sectionIndex, 1, 1).bodyHeight,
|
|
1670
|
+
this.getPageBands(dims, sectionIndex, 2, 1).bodyHeight,
|
|
1671
|
+
this.getPageBands(dims, sectionIndex, 2, 2).bodyHeight
|
|
1643
1672
|
);
|
|
1644
1673
|
}
|
|
1645
1674
|
/**
|
|
@@ -2163,7 +2192,7 @@ var PaginationEngine = class {
|
|
|
2163
2192
|
/**
|
|
2164
2193
|
* Adds footnotes to a page container, including continuation content.
|
|
2165
2194
|
*/
|
|
2166
|
-
addPageFootnotes(pageBox, footnoteIds, dims, footnoteHeight, continuation, partialFootnotes) {
|
|
2195
|
+
addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes) {
|
|
2167
2196
|
const hasContinuation = continuation && continuation.remainingElements.length > 0;
|
|
2168
2197
|
if (footnoteIds.length === 0 && !hasContinuation) {
|
|
2169
2198
|
return;
|
|
@@ -2174,12 +2203,12 @@ var PaginationEngine = class {
|
|
|
2174
2203
|
const partialFootnoteIds = new Set(partialFootnotes?.map((p) => p.footnoteId) || []);
|
|
2175
2204
|
const maxFootnoteHeight = Math.min(
|
|
2176
2205
|
footnoteHeight,
|
|
2177
|
-
|
|
2206
|
+
bands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO
|
|
2178
2207
|
);
|
|
2179
2208
|
const footnotesDiv = document.createElement("div");
|
|
2180
2209
|
footnotesDiv.className = `${this.cssPrefix}footnotes`;
|
|
2181
2210
|
footnotesDiv.style.position = "absolute";
|
|
2182
|
-
footnotesDiv.style.bottom = `${dims.
|
|
2211
|
+
footnotesDiv.style.bottom = `${dims.pageHeight - (bands.bodyTop + bands.bodyHeight)}pt`;
|
|
2183
2212
|
footnotesDiv.style.left = `${dims.marginLeft}pt`;
|
|
2184
2213
|
footnotesDiv.style.width = `${dims.contentWidth}pt`;
|
|
2185
2214
|
footnotesDiv.style.boxSizing = "border-box";
|
|
@@ -2253,50 +2282,51 @@ var PaginationEngine = class {
|
|
|
2253
2282
|
return sectionHf.footerDefault;
|
|
2254
2283
|
}
|
|
2255
2284
|
/**
|
|
2256
|
-
*
|
|
2257
|
-
*
|
|
2258
|
-
*
|
|
2259
|
-
*
|
|
2260
|
-
*
|
|
2285
|
+
* The header, body, and footer bands for one page position.
|
|
2286
|
+
*
|
|
2287
|
+
* The single owner of "where does anything sit vertically on this page" — placement in
|
|
2288
|
+
* {@link createPage}, the body budget the flow loop spends, and the note area's anchor all
|
|
2289
|
+
* read it, so those three cannot disagree about where the body ends.
|
|
2290
|
+
*
|
|
2291
|
+
* Deterministic: it depends only on the section's page setup and the registry's pre-measured
|
|
2292
|
+
* story heights, never on the page's content, which is what keeps it lazy-loading compatible.
|
|
2261
2293
|
*/
|
|
2262
|
-
|
|
2294
|
+
getPageBands(dims, sectionIndex, pageInSection, globalPageNumber) {
|
|
2263
2295
|
const sectionHf = this.hfRegistry.get(sectionIndex);
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
}
|
|
2291
|
-
}
|
|
2292
|
-
const headerExpansion = headerHeight - dims.marginTop;
|
|
2293
|
-
const footerExpansion = footerHeight - dims.marginBottom;
|
|
2294
|
-
const contentHeight = dims.contentHeight - headerExpansion - footerExpansion;
|
|
2295
|
-
return { headerHeight, footerHeight, contentHeight };
|
|
2296
|
+
return resolvePageBands(
|
|
2297
|
+
dims,
|
|
2298
|
+
this.selectStoryHeight(
|
|
2299
|
+
sectionHf?.headerFirstHeight,
|
|
2300
|
+
sectionHf?.headerEvenHeight,
|
|
2301
|
+
sectionHf?.headerDefaultHeight,
|
|
2302
|
+
pageInSection,
|
|
2303
|
+
globalPageNumber
|
|
2304
|
+
),
|
|
2305
|
+
this.selectStoryHeight(
|
|
2306
|
+
sectionHf?.footerFirstHeight,
|
|
2307
|
+
sectionHf?.footerEvenHeight,
|
|
2308
|
+
sectionHf?.footerDefaultHeight,
|
|
2309
|
+
pageInSection,
|
|
2310
|
+
globalPageNumber
|
|
2311
|
+
)
|
|
2312
|
+
);
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* The measured height of the running story this page position selects, mirroring
|
|
2316
|
+
* {@link selectHeader}/{@link selectFooter}. Zero when the page has no such story.
|
|
2317
|
+
*/
|
|
2318
|
+
selectStoryHeight(first, even, fallback, pageInSection, globalPageNumber) {
|
|
2319
|
+
if (pageInSection === 1 && first != null) return first;
|
|
2320
|
+
if (globalPageNumber % 2 === 0 && even != null) return even;
|
|
2321
|
+
return fallback ?? 0;
|
|
2296
2322
|
}
|
|
2297
2323
|
/**
|
|
2298
2324
|
* Measures the content height of a header or footer element.
|
|
2299
|
-
*
|
|
2325
|
+
*
|
|
2326
|
+
* This is what tells {@link resolvePageBands} whether the story stays inside its margin or
|
|
2327
|
+
* pushes the body, so it must measure the story ALONE — any padding added here would have to
|
|
2328
|
+
* be added to the rendered band too, and the two drifting apart is exactly how a header
|
|
2329
|
+
* silently starts overlapping body text.
|
|
2300
2330
|
*/
|
|
2301
2331
|
measureHeaderFooterHeight(source, contentWidth) {
|
|
2302
2332
|
const measureContainer = document.createElement("div");
|
|
@@ -2304,7 +2334,6 @@ var PaginationEngine = class {
|
|
|
2304
2334
|
measureContainer.style.visibility = "hidden";
|
|
2305
2335
|
measureContainer.style.width = `${contentWidth}pt`;
|
|
2306
2336
|
measureContainer.style.left = "-9999px";
|
|
2307
|
-
measureContainer.style.paddingBottom = "4pt";
|
|
2308
2337
|
for (const child of Array.from(source.childNodes)) {
|
|
2309
2338
|
measureContainer.appendChild(child.cloneNode(true));
|
|
2310
2339
|
}
|
|
@@ -2324,7 +2353,7 @@ var PaginationEngine = class {
|
|
|
2324
2353
|
let currentContent = [];
|
|
2325
2354
|
let pageNumber = startPageNumber;
|
|
2326
2355
|
let pageInSection = 1;
|
|
2327
|
-
let {
|
|
2356
|
+
let { bodyHeight: effectiveContentHeight } = this.getPageBands(
|
|
2328
2357
|
dims,
|
|
2329
2358
|
sectionIndex,
|
|
2330
2359
|
pageInSection,
|
|
@@ -2359,8 +2388,8 @@ var PaginationEngine = class {
|
|
|
2359
2388
|
pageNumber++;
|
|
2360
2389
|
pageInSection++;
|
|
2361
2390
|
currentContent = [];
|
|
2362
|
-
const
|
|
2363
|
-
effectiveContentHeight =
|
|
2391
|
+
const newBands = this.getPageBands(dims, sectionIndex, pageInSection, pageNumber);
|
|
2392
|
+
effectiveContentHeight = newBands.bodyHeight;
|
|
2364
2393
|
remainingHeight = effectiveContentHeight;
|
|
2365
2394
|
prevMarginBottomPt = 0;
|
|
2366
2395
|
currentFootnoteIds = [];
|
|
@@ -2422,7 +2451,7 @@ var PaginationEngine = class {
|
|
|
2422
2451
|
) + additionalChainFootnoteHeight;
|
|
2423
2452
|
const currentAvailableHeight = remainingHeight - currentFootnoteHeight;
|
|
2424
2453
|
if (currentChainHeight > currentAvailableHeight) {
|
|
2425
|
-
const
|
|
2454
|
+
const nextPageBands = this.getPageBands(
|
|
2426
2455
|
dims,
|
|
2427
2456
|
sectionIndex,
|
|
2428
2457
|
pageInSection + 1,
|
|
@@ -2438,7 +2467,7 @@ var PaginationEngine = class {
|
|
|
2438
2467
|
dims.contentWidth,
|
|
2439
2468
|
nextPageContinuation
|
|
2440
2469
|
);
|
|
2441
|
-
if (freshChainBodyHeight + freshChainFootnoteHeight <=
|
|
2470
|
+
if (freshChainBodyHeight + freshChainFootnoteHeight <= nextPageBands.bodyHeight) {
|
|
2442
2471
|
finishPage();
|
|
2443
2472
|
}
|
|
2444
2473
|
}
|
|
@@ -2607,6 +2636,161 @@ var PaginationEngine = class {
|
|
|
2607
2636
|
if (el.getAttribute("contenteditable") !== null) el.setAttribute("contenteditable", "false");
|
|
2608
2637
|
}
|
|
2609
2638
|
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Resolves floating DrawingML objects after their anchor paragraphs have landed on a page.
|
|
2641
|
+
*
|
|
2642
|
+
* The converter deliberately carries the OOXML bases and offsets as data instead of flattening
|
|
2643
|
+
* them into CSS: page/margin/column bases belong to the page, while paragraph/line/character
|
|
2644
|
+
* bases belong to the laid-out anchor. Once both coordinate systems exist, promote the object
|
|
2645
|
+
* from the clipped text column into the page box and position it in one shared point space.
|
|
2646
|
+
*/
|
|
2647
|
+
positionDrawingAnchors(pageBox, contentArea, dims, pageNumber) {
|
|
2648
|
+
const anchors = Array.from(
|
|
2649
|
+
contentArea.querySelectorAll('[data-docx-drawing-anchor="true"]')
|
|
2650
|
+
);
|
|
2651
|
+
if (anchors.length === 0) return;
|
|
2652
|
+
const pageRect = pageBox.getBoundingClientRect();
|
|
2653
|
+
const pixelsPerPoint = pageRect.width / dims.pageWidth;
|
|
2654
|
+
if (!(pixelsPerPoint > 0)) return;
|
|
2655
|
+
for (const anchor of anchors) {
|
|
2656
|
+
const staticRect = anchor.getBoundingClientRect();
|
|
2657
|
+
const paragraph = anchor.closest("p, h1, h2, h3, h4, h5, h6");
|
|
2658
|
+
const paragraphRect = paragraph?.getBoundingClientRect() ?? staticRect;
|
|
2659
|
+
const toPageX = (x) => (x - pageRect.left) / pixelsPerPoint;
|
|
2660
|
+
const toPageY = (y) => (y - pageRect.top) / pixelsPerPoint;
|
|
2661
|
+
const context = {
|
|
2662
|
+
staticLeft: toPageX(staticRect.left),
|
|
2663
|
+
staticTop: toPageY(staticRect.top),
|
|
2664
|
+
lineHeight: paragraph ? (parseFloat(getComputedStyle(paragraph).lineHeight) || staticRect.height) / pixelsPerPoint : staticRect.height / pixelsPerPoint,
|
|
2665
|
+
paragraphLeft: toPageX(paragraphRect.left),
|
|
2666
|
+
paragraphTop: toPageY(paragraphRect.top),
|
|
2667
|
+
paragraphWidth: paragraphRect.width / pixelsPerPoint,
|
|
2668
|
+
paragraphHeight: paragraphRect.height / pixelsPerPoint
|
|
2669
|
+
};
|
|
2670
|
+
const widthReference = this.horizontalAnchorReference(
|
|
2671
|
+
anchor.getAttribute("data-docx-anchor-width-relative") ?? "margin",
|
|
2672
|
+
dims,
|
|
2673
|
+
pageNumber,
|
|
2674
|
+
context
|
|
2675
|
+
);
|
|
2676
|
+
const widthPercent = this.anchorNumber(anchor, "width-percent");
|
|
2677
|
+
if (widthPercent !== void 0) {
|
|
2678
|
+
anchor.style.width = `${widthReference.size * widthPercent / 100}pt`;
|
|
2679
|
+
}
|
|
2680
|
+
const heightReference = this.verticalAnchorReference(
|
|
2681
|
+
anchor.getAttribute("data-docx-anchor-height-relative") ?? "margin",
|
|
2682
|
+
dims,
|
|
2683
|
+
pageNumber,
|
|
2684
|
+
context
|
|
2685
|
+
);
|
|
2686
|
+
const heightPercent = this.anchorNumber(anchor, "height-percent");
|
|
2687
|
+
if (heightPercent !== void 0 && anchor.dataset.docxAnchorAutofit !== "true") {
|
|
2688
|
+
anchor.style.height = `${heightReference.size * heightPercent / 100}pt`;
|
|
2689
|
+
}
|
|
2690
|
+
const sizedRect = anchor.getBoundingClientRect();
|
|
2691
|
+
const width = sizedRect.width / pixelsPerPoint;
|
|
2692
|
+
const height = sizedRect.height / pixelsPerPoint;
|
|
2693
|
+
const horizontal2 = this.horizontalAnchorReference(
|
|
2694
|
+
anchor.getAttribute("data-docx-anchor-h-relative") ?? "column",
|
|
2695
|
+
dims,
|
|
2696
|
+
pageNumber,
|
|
2697
|
+
context
|
|
2698
|
+
);
|
|
2699
|
+
const vertical2 = this.verticalAnchorReference(
|
|
2700
|
+
anchor.getAttribute("data-docx-anchor-v-relative") ?? "paragraph",
|
|
2701
|
+
dims,
|
|
2702
|
+
pageNumber,
|
|
2703
|
+
context
|
|
2704
|
+
);
|
|
2705
|
+
const left2 = this.resolveAnchorAxis(
|
|
2706
|
+
horizontal2,
|
|
2707
|
+
width,
|
|
2708
|
+
anchor.getAttribute("data-docx-anchor-h-align"),
|
|
2709
|
+
this.anchorNumber(anchor, "h-offset"),
|
|
2710
|
+
pageNumber
|
|
2711
|
+
);
|
|
2712
|
+
const top2 = this.resolveAnchorAxis(
|
|
2713
|
+
vertical2,
|
|
2714
|
+
height,
|
|
2715
|
+
anchor.getAttribute("data-docx-anchor-v-align"),
|
|
2716
|
+
this.anchorNumber(anchor, "v-offset"),
|
|
2717
|
+
pageNumber
|
|
2718
|
+
);
|
|
2719
|
+
pageBox.appendChild(anchor);
|
|
2720
|
+
anchor.style.position = "absolute";
|
|
2721
|
+
anchor.style.left = `${left2}pt`;
|
|
2722
|
+
anchor.style.top = `${top2}pt`;
|
|
2723
|
+
anchor.style.margin = "0";
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
anchorNumber(anchor, suffix) {
|
|
2727
|
+
const raw = anchor.getAttribute(`data-docx-anchor-${suffix}`);
|
|
2728
|
+
if (raw === null) return void 0;
|
|
2729
|
+
const value = Number(raw);
|
|
2730
|
+
return Number.isFinite(value) ? value : void 0;
|
|
2731
|
+
}
|
|
2732
|
+
horizontalAnchorReference(relativeFrom, dims, pageNumber, context) {
|
|
2733
|
+
const leftMargin = { start: 0, size: dims.marginLeft };
|
|
2734
|
+
const rightMargin = {
|
|
2735
|
+
start: dims.marginLeft + dims.contentWidth,
|
|
2736
|
+
size: dims.marginRight
|
|
2737
|
+
};
|
|
2738
|
+
switch (relativeFrom) {
|
|
2739
|
+
case "page":
|
|
2740
|
+
return { start: 0, size: dims.pageWidth };
|
|
2741
|
+
case "character":
|
|
2742
|
+
return { start: context.staticLeft, size: 0 };
|
|
2743
|
+
case "leftMargin":
|
|
2744
|
+
return leftMargin;
|
|
2745
|
+
case "rightMargin":
|
|
2746
|
+
return rightMargin;
|
|
2747
|
+
case "insideMargin":
|
|
2748
|
+
return pageNumber % 2 === 1 ? leftMargin : rightMargin;
|
|
2749
|
+
case "outsideMargin":
|
|
2750
|
+
return pageNumber % 2 === 1 ? rightMargin : leftMargin;
|
|
2751
|
+
case "paragraph":
|
|
2752
|
+
return { start: context.paragraphLeft, size: context.paragraphWidth };
|
|
2753
|
+
case "column":
|
|
2754
|
+
case "margin":
|
|
2755
|
+
default:
|
|
2756
|
+
return { start: dims.marginLeft, size: dims.contentWidth };
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
verticalAnchorReference(relativeFrom, dims, pageNumber, context) {
|
|
2760
|
+
const topMargin = { start: 0, size: dims.marginTop };
|
|
2761
|
+
const bottomMargin = {
|
|
2762
|
+
start: dims.marginTop + dims.contentHeight,
|
|
2763
|
+
size: dims.marginBottom
|
|
2764
|
+
};
|
|
2765
|
+
switch (relativeFrom) {
|
|
2766
|
+
case "page":
|
|
2767
|
+
return { start: 0, size: dims.pageHeight };
|
|
2768
|
+
case "paragraph":
|
|
2769
|
+
return { start: context.paragraphTop, size: context.paragraphHeight };
|
|
2770
|
+
case "line":
|
|
2771
|
+
return { start: context.staticTop, size: context.lineHeight };
|
|
2772
|
+
case "topMargin":
|
|
2773
|
+
return topMargin;
|
|
2774
|
+
case "bottomMargin":
|
|
2775
|
+
return bottomMargin;
|
|
2776
|
+
case "insideMargin":
|
|
2777
|
+
return pageNumber % 2 === 1 ? topMargin : bottomMargin;
|
|
2778
|
+
case "outsideMargin":
|
|
2779
|
+
return pageNumber % 2 === 1 ? bottomMargin : topMargin;
|
|
2780
|
+
case "margin":
|
|
2781
|
+
default:
|
|
2782
|
+
return { start: dims.marginTop, size: dims.contentHeight };
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
resolveAnchorAxis(reference, objectSize, alignment, offset, pageNumber) {
|
|
2786
|
+
if (offset !== void 0) return reference.start + offset;
|
|
2787
|
+
let fraction = 0;
|
|
2788
|
+
if (alignment === "center") fraction = 0.5;
|
|
2789
|
+
else if (alignment === "right" || alignment === "bottom") fraction = 1;
|
|
2790
|
+
else if (alignment === "inside") fraction = pageNumber % 2 === 1 ? 0 : 1;
|
|
2791
|
+
else if (alignment === "outside") fraction = pageNumber % 2 === 1 ? 1 : 0;
|
|
2792
|
+
return reference.start + (reference.size - objectSize) * fraction;
|
|
2793
|
+
}
|
|
2610
2794
|
/**
|
|
2611
2795
|
* Creates a page container element.
|
|
2612
2796
|
*/
|
|
@@ -2633,22 +2817,22 @@ var PaginationEngine = class {
|
|
|
2633
2817
|
pageBox.dataset.pageNumber = String(pageNumber);
|
|
2634
2818
|
pageBox.dataset.sectionIndex = String(sectionIndex);
|
|
2635
2819
|
pageBox.dataset.pageInSection = String(pageInSection);
|
|
2636
|
-
const
|
|
2820
|
+
const bands = this.getPageBands(dims, sectionIndex, pageInSection, pageNumber);
|
|
2637
2821
|
const headerSource = this.selectHeader(sectionIndex, pageInSection, pageNumber);
|
|
2638
2822
|
if (headerSource) {
|
|
2639
2823
|
const headerDiv = document.createElement("div");
|
|
2640
2824
|
headerDiv.className = `${this.cssPrefix}header`;
|
|
2641
2825
|
headerDiv.style.position = "absolute";
|
|
2642
|
-
headerDiv.style.top =
|
|
2826
|
+
headerDiv.style.top = `${bands.headerTop}pt`;
|
|
2827
|
+
headerDiv.style.bottom = "auto";
|
|
2643
2828
|
headerDiv.style.left = `${dims.marginLeft}pt`;
|
|
2644
2829
|
headerDiv.style.width = `${dims.contentWidth}pt`;
|
|
2645
|
-
headerDiv.style.height = `${
|
|
2830
|
+
headerDiv.style.height = `${bands.headerHeight}pt`;
|
|
2646
2831
|
headerDiv.style.overflow = "hidden";
|
|
2647
2832
|
headerDiv.style.boxSizing = "border-box";
|
|
2648
2833
|
headerDiv.style.display = "flex";
|
|
2649
2834
|
headerDiv.style.flexDirection = "column";
|
|
2650
|
-
headerDiv.style.justifyContent = "flex-
|
|
2651
|
-
headerDiv.style.paddingBottom = "4pt";
|
|
2835
|
+
headerDiv.style.justifyContent = "flex-start";
|
|
2652
2836
|
for (const child of Array.from(headerSource.childNodes)) {
|
|
2653
2837
|
const clonedheaderDiv = child.cloneNode(true);
|
|
2654
2838
|
if (clonedheaderDiv.nodeType === 1) this.makeClonedStoryInert(clonedheaderDiv);
|
|
@@ -2656,8 +2840,8 @@ var PaginationEngine = class {
|
|
|
2656
2840
|
}
|
|
2657
2841
|
pageBox.appendChild(headerDiv);
|
|
2658
2842
|
}
|
|
2659
|
-
const contentAreaTop =
|
|
2660
|
-
const contentAreaHeight =
|
|
2843
|
+
const contentAreaTop = bands.bodyTop;
|
|
2844
|
+
const contentAreaHeight = bands.bodyHeight;
|
|
2661
2845
|
const contentArea = document.createElement("div");
|
|
2662
2846
|
contentArea.className = `${this.cssPrefix}content`;
|
|
2663
2847
|
contentArea.style.position = "absolute";
|
|
@@ -2672,23 +2856,23 @@ var PaginationEngine = class {
|
|
|
2672
2856
|
pageBox.appendChild(contentArea);
|
|
2673
2857
|
const hasContinuation = continuation && continuation.remainingElements.length > 0;
|
|
2674
2858
|
if (footnoteIds.length > 0 || hasContinuation) {
|
|
2675
|
-
this.addPageFootnotes(pageBox, footnoteIds, dims, footnoteHeight, continuation, partialFootnotes);
|
|
2859
|
+
this.addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes);
|
|
2676
2860
|
}
|
|
2677
2861
|
const footerSource = this.selectFooter(sectionIndex, pageInSection, pageNumber);
|
|
2678
2862
|
if (footerSource) {
|
|
2679
2863
|
const footerDiv = document.createElement("div");
|
|
2680
2864
|
footerDiv.className = `${this.cssPrefix}footer`;
|
|
2681
2865
|
footerDiv.style.position = "absolute";
|
|
2682
|
-
footerDiv.style.
|
|
2866
|
+
footerDiv.style.top = "auto";
|
|
2867
|
+
footerDiv.style.bottom = `${dims.footerDistance}pt`;
|
|
2683
2868
|
footerDiv.style.left = `${dims.marginLeft}pt`;
|
|
2684
2869
|
footerDiv.style.width = `${dims.contentWidth}pt`;
|
|
2685
|
-
footerDiv.style.height = `${
|
|
2870
|
+
footerDiv.style.height = `${bands.footerHeight}pt`;
|
|
2686
2871
|
footerDiv.style.overflow = "hidden";
|
|
2687
2872
|
footerDiv.style.boxSizing = "border-box";
|
|
2688
2873
|
footerDiv.style.display = "flex";
|
|
2689
2874
|
footerDiv.style.flexDirection = "column";
|
|
2690
|
-
footerDiv.style.justifyContent = "flex-
|
|
2691
|
-
footerDiv.style.paddingTop = "4pt";
|
|
2875
|
+
footerDiv.style.justifyContent = "flex-end";
|
|
2692
2876
|
for (const child of Array.from(footerSource.childNodes)) {
|
|
2693
2877
|
const clonedfooterDiv = child.cloneNode(true);
|
|
2694
2878
|
if (clonedfooterDiv.nodeType === 1) this.makeClonedStoryInert(clonedfooterDiv);
|
|
@@ -2703,6 +2887,7 @@ var PaginationEngine = class {
|
|
|
2703
2887
|
pageBox.appendChild(pageNum);
|
|
2704
2888
|
}
|
|
2705
2889
|
this.containerElement.appendChild(pageBox);
|
|
2890
|
+
this.positionDrawingAnchors(pageBox, contentArea, dims, pageNumber);
|
|
2706
2891
|
const notesEl = pageBox.querySelector(`.${this.cssPrefix}footnotes`);
|
|
2707
2892
|
if (notesEl) {
|
|
2708
2893
|
const notesHeightPt = pxToPt(notesEl.getBoundingClientRect().height);
|
|
@@ -6077,6 +6262,19 @@ function serializeInlineMarkdown(block) {
|
|
|
6077
6262
|
function isListBlock(block) {
|
|
6078
6263
|
return !!block.querySelector(":scope > [data-list-marker]");
|
|
6079
6264
|
}
|
|
6265
|
+
function ensureListMarkerSeparator(block) {
|
|
6266
|
+
const marker = block.querySelector(":scope > [data-list-marker]");
|
|
6267
|
+
if (!marker) return;
|
|
6268
|
+
const next = marker.nextElementSibling;
|
|
6269
|
+
if (next?.hasAttribute("data-editor-list-separator")) return;
|
|
6270
|
+
const separator = block.ownerDocument.createElement("span");
|
|
6271
|
+
separator.setAttribute("data-editor-list-separator", "");
|
|
6272
|
+
separator.setAttribute("data-list-marker", "true");
|
|
6273
|
+
separator.setAttribute("aria-hidden", "true");
|
|
6274
|
+
separator.style.display = "none";
|
|
6275
|
+
separator.textContent = " ";
|
|
6276
|
+
marker.after(separator);
|
|
6277
|
+
}
|
|
6080
6278
|
var GENERATED_CHROME_SELECTOR = '[data-list-marker], a.footnote-ref, a.endnote-ref, a[class$="-backref"]';
|
|
6081
6279
|
function isGeneratedChrome(node) {
|
|
6082
6280
|
return node?.nodeType === 1 && !!node.matches?.(GENERATED_CHROME_SELECTOR);
|
|
@@ -7367,6 +7565,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
7367
7565
|
const unid = el.getAttribute("data-anchor");
|
|
7368
7566
|
if (!unid || !this.anchorIdOf(el)) return;
|
|
7369
7567
|
el.setAttribute("contenteditable", "true");
|
|
7568
|
+
ensureListMarkerSeparator(el);
|
|
7370
7569
|
el.querySelectorAll(GENERATED_CHROME_SELECTOR).forEach((m) => m.setAttribute("contenteditable", "false"));
|
|
7371
7570
|
el.dataset.committedText = blockContentText(el);
|
|
7372
7571
|
el.addEventListener("focus", () => {
|
|
@@ -8229,8 +8428,8 @@ var DocxEditor = class _DocxEditor {
|
|
|
8229
8428
|
* editable `data-anchor` blocks in the notes section, so editing it afterwards needs no new op.
|
|
8230
8429
|
*
|
|
8231
8430
|
* Body blocks only: Word disallows a note reference inside a header/footer story or inside
|
|
8232
|
-
* another note, and the session rejects those with `AnchorWrongKind`.
|
|
8233
|
-
*
|
|
8431
|
+
* another note, and the session rejects those with `AnchorWrongKind`. Reconciliation creates
|
|
8432
|
+
* the first notes section when needed and renumbers every affected citation in place.
|
|
8234
8433
|
*/
|
|
8235
8434
|
insertFootnote(markdown = "New footnote.") {
|
|
8236
8435
|
this.insertNote("footnote", markdown);
|
|
@@ -8622,7 +8821,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
8622
8821
|
* the current node — never a section div (multi-child) or the edit root. */
|
|
8623
8822
|
unitWrapperOf(el) {
|
|
8624
8823
|
let n = el;
|
|
8625
|
-
while (n.parentElement && n.parentElement !== this.editRoot && n.parentElement.tagName === "DIV" && !n.parentElement.hasAttribute("data-anchor") && n.parentElement.childElementCount === 1) {
|
|
8824
|
+
while (n.parentElement && n.parentElement !== this.editRoot && n.parentElement.tagName === "DIV" && !n.parentElement.hasAttribute("data-section-index") && !n.parentElement.hasAttribute("data-anchor") && n.parentElement.childElementCount === 1) {
|
|
8626
8825
|
n = n.parentElement;
|
|
8627
8826
|
}
|
|
8628
8827
|
return n;
|
|
@@ -8658,6 +8857,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
8658
8857
|
const pureRemoved = diff.removed.filter(
|
|
8659
8858
|
(i) => !diff.substituted.some((s) => s.oldIndex === i) && !movedOld.has(i)
|
|
8660
8859
|
);
|
|
8860
|
+
const appliedFresh = /* @__PURE__ */ new Set();
|
|
8661
8861
|
const nodeAt = (j) => {
|
|
8662
8862
|
const oi = diff.keep.get(j);
|
|
8663
8863
|
if (oi !== void 0) return oldNodes[oi];
|
|
@@ -8665,7 +8865,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
8665
8865
|
if (movedOi !== void 0) return oldNodes[movedOi];
|
|
8666
8866
|
if (subOldByNew.has(j)) return fresh.get(j);
|
|
8667
8867
|
const f = fresh.get(j);
|
|
8668
|
-
return f &&
|
|
8868
|
+
return f && appliedFresh.has(j) ? f : null;
|
|
8669
8869
|
};
|
|
8670
8870
|
for (const j of pureAdded) {
|
|
8671
8871
|
const el = fresh.get(j);
|
|
@@ -8680,6 +8880,7 @@ var DocxEditor = class _DocxEditor {
|
|
|
8680
8880
|
if (prevW) prevW.after(el);
|
|
8681
8881
|
else if (nextW) nextW.before(el);
|
|
8682
8882
|
else return "insert with no anchored neighbor";
|
|
8883
|
+
appliedFresh.add(j);
|
|
8683
8884
|
this.wireUnit(el, units[j]);
|
|
8684
8885
|
}
|
|
8685
8886
|
for (const i of pureRemoved) {
|
|
@@ -8718,13 +8919,13 @@ var DocxEditor = class _DocxEditor {
|
|
|
8718
8919
|
if (anchorEl) this.wireBlock(anchorEl);
|
|
8719
8920
|
root.querySelectorAll("[data-anchor]").forEach((b) => this.wireBlock(b));
|
|
8720
8921
|
}
|
|
8721
|
-
/** Old-sequence diff state for one notes section. `null` requests remount
|
|
8722
|
-
* stampable
|
|
8922
|
+
/** Old-sequence diff state for one notes section. `null` requests remount when an
|
|
8923
|
+
* existing list is not stampable; an absent list is the valid first-note case. */
|
|
8723
8924
|
notesDiff(sectionClass, units) {
|
|
8724
8925
|
const ol = this.editRoot.querySelector(`section.${sectionClass} > ol`);
|
|
8725
8926
|
const lis = ol ? Array.from(ol.children).filter((c) => c.tagName === "LI") : [];
|
|
8726
8927
|
if (units.length === 0 && lis.length === 0) return { lis, diff: diffUnits([], []) };
|
|
8727
|
-
if (!ol) return
|
|
8928
|
+
if (!ol) return { lis, diff: diffUnits([], units) };
|
|
8728
8929
|
const tokens = [];
|
|
8729
8930
|
for (const li of lis) {
|
|
8730
8931
|
const unid = li.getAttribute("data-note-anchor");
|
|
@@ -8741,7 +8942,20 @@ var DocxEditor = class _DocxEditor {
|
|
|
8741
8942
|
this.editRoot.querySelector(`section.${sectionClass}`)?.remove();
|
|
8742
8943
|
return;
|
|
8743
8944
|
}
|
|
8744
|
-
|
|
8945
|
+
let section = this.editRoot.querySelector(`:scope > section.${sectionClass}`);
|
|
8946
|
+
let ol = section?.querySelector(`:scope > ol`) ?? null;
|
|
8947
|
+
if (!ol) {
|
|
8948
|
+
if (!section) {
|
|
8949
|
+
section = document.createElement("section");
|
|
8950
|
+
section.className = sectionClass;
|
|
8951
|
+
const following = sectionClass === "footnotes" ? this.editRoot.querySelector(`:scope > section.endnotes`) : null;
|
|
8952
|
+
if (following) following.before(section);
|
|
8953
|
+
else this.editRoot.append(section);
|
|
8954
|
+
}
|
|
8955
|
+
if (!section.querySelector(":scope > hr")) section.prepend(document.createElement("hr"));
|
|
8956
|
+
ol = document.createElement("ol");
|
|
8957
|
+
section.append(ol);
|
|
8958
|
+
}
|
|
8745
8959
|
const prefix = sectionClass === "footnotes" ? "fn" : "en";
|
|
8746
8960
|
const nodes = [];
|
|
8747
8961
|
for (let j = 0; j < units.length; j++) {
|
|
@@ -8878,23 +9092,38 @@ var DocxEditor = class _DocxEditor {
|
|
|
8878
9092
|
};
|
|
8879
9093
|
|
|
8880
9094
|
// src/ribbon-chrome.ts
|
|
8881
|
-
var RIBBON_STYLE_VERSION = "
|
|
9095
|
+
var RIBBON_STYLE_VERSION = "8";
|
|
8882
9096
|
var RIBBON_STYLE_ATTR = "data-docxodus-ribbon-styles";
|
|
8883
9097
|
var RIBBON_CSS = `
|
|
8884
9098
|
.dxr {
|
|
8885
|
-
|
|
9099
|
+
/* OS-Legal design tokens (github.com/Open-Source-Legal/OS-Legal-Style):
|
|
9100
|
+
deep-teal accent, slate foreground scale, warm neutral surfaces, and
|
|
9101
|
+
"light touch" shadows at 0.03-0.06 opacity \u2014 structure over decoration. */
|
|
9102
|
+
--dxr-ink: #1e293b;
|
|
8886
9103
|
--dxr-sheet: #ffffff;
|
|
8887
|
-
--dxr-chrome: #
|
|
8888
|
-
--dxr-chrome-sunk: #
|
|
8889
|
-
--dxr-rule: #
|
|
8890
|
-
--dxr-
|
|
8891
|
-
--dxr-
|
|
8892
|
-
--dxr-
|
|
8893
|
-
--dxr-
|
|
8894
|
-
--dxr-
|
|
8895
|
-
--dxr-
|
|
8896
|
-
--dxr-
|
|
9104
|
+
--dxr-chrome: #ffffff;
|
|
9105
|
+
--dxr-chrome-sunk: #f8fafc;
|
|
9106
|
+
--dxr-rule: #e2e8f0;
|
|
9107
|
+
--dxr-rule-strong: #cbd5e1;
|
|
9108
|
+
--dxr-accent: #0f766e;
|
|
9109
|
+
--dxr-accent-hover: #0d9488;
|
|
9110
|
+
--dxr-accent-active: #115e59;
|
|
9111
|
+
--dxr-wash: #f0fdfa;
|
|
9112
|
+
--dxr-wash-on: #ccfbf1;
|
|
9113
|
+
--dxr-muted: #475569;
|
|
9114
|
+
--dxr-faint: #94a3b8;
|
|
9115
|
+
--dxr-data: #0f766e;
|
|
9116
|
+
--dxr-danger: #dc2626;
|
|
9117
|
+
--dxr-danger-wash: #fef2f2;
|
|
9118
|
+
--dxr-desk: #f1f5f9;
|
|
9119
|
+
--dxr-ui: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
9120
|
+
--dxr-serif: Georgia, "Times New Roman", serif;
|
|
8897
9121
|
--dxr-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
|
|
9122
|
+
--dxr-shadow-sm: 0 1px 2px rgba(15, 23, 42, .04);
|
|
9123
|
+
--dxr-shadow-md: 0 1px 3px rgba(15, 23, 42, .06), 0 4px 6px rgba(15, 23, 42, .03);
|
|
9124
|
+
--dxr-shadow-lg: 0 4px 6px rgba(15, 23, 42, .05), 0 10px 15px rgba(15, 23, 42, .04);
|
|
9125
|
+
--dxr-shadow-xl: 0 8px 16px rgba(15, 23, 42, .06), 0 20px 25px rgba(15, 23, 42, .05);
|
|
9126
|
+
--dxr-ease: cubic-bezier(.4, 0, .2, 1);
|
|
8898
9127
|
--dxr-tap: 30px;
|
|
8899
9128
|
|
|
8900
9129
|
position: relative;
|
|
@@ -8910,6 +9139,18 @@ var RIBBON_CSS = `
|
|
|
8910
9139
|
}
|
|
8911
9140
|
.dxr *, .dxr *::before, .dxr *::after { box-sizing: border-box; }
|
|
8912
9141
|
|
|
9142
|
+
/* \u2500\u2500 Card frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
9143
|
+
A drop-in embed carries its OWN boundary instead of hoping the host clips it:
|
|
9144
|
+
rounded corners, a hairline, and the house elevation. overflow: clip keeps
|
|
9145
|
+
the sticky chrome, scrollbars, and the loading overlay inside the curve.
|
|
9146
|
+
Full-bleed hosts mount with data-frame="flush" and stay edge-to-edge. */
|
|
9147
|
+
.dxr[data-frame="card"] {
|
|
9148
|
+
border: 1px solid var(--dxr-rule);
|
|
9149
|
+
border-radius: 14px;
|
|
9150
|
+
box-shadow: var(--dxr-shadow-xl);
|
|
9151
|
+
overflow: clip;
|
|
9152
|
+
}
|
|
9153
|
+
|
|
8913
9154
|
/* Touch devices get bigger hit targets everywhere the token is used. */
|
|
8914
9155
|
@media (pointer: coarse) { .dxr { --dxr-tap: 40px; } }
|
|
8915
9156
|
|
|
@@ -8938,12 +9179,13 @@ var RIBBON_CSS = `
|
|
|
8938
9179
|
font-weight: 600;
|
|
8939
9180
|
letter-spacing: -.01em;
|
|
8940
9181
|
}
|
|
9182
|
+
/* A filled circle, echoing the OS-Legal "Node" motif rather than a diamond. */
|
|
8941
9183
|
.dxr-brand .dxr-mark {
|
|
8942
9184
|
flex: 0 0 auto;
|
|
8943
9185
|
width: 9px;
|
|
8944
9186
|
height: 9px;
|
|
9187
|
+
border-radius: 50%;
|
|
8945
9188
|
background: var(--dxr-accent);
|
|
8946
|
-
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
|
|
8947
9189
|
}
|
|
8948
9190
|
.dxr-brand .dxr-docname {
|
|
8949
9191
|
overflow: hidden;
|
|
@@ -8975,25 +9217,25 @@ var RIBBON_CSS = `
|
|
|
8975
9217
|
scrollbar-width: none;
|
|
8976
9218
|
}
|
|
8977
9219
|
.dxr-tabs::-webkit-scrollbar { display: none; }
|
|
9220
|
+
/* Line-variant tabs (the house Tabs default): no boxes, no fills \u2014 the selected
|
|
9221
|
+
tab is a 2px accent underline sitting on the panel's own hairline. */
|
|
8978
9222
|
.dxr-tab {
|
|
8979
9223
|
flex: 0 0 auto;
|
|
8980
|
-
padding:
|
|
8981
|
-
border:
|
|
8982
|
-
border-bottom: none;
|
|
8983
|
-
border-radius: 5px 5px 0 0;
|
|
9224
|
+
padding: 7px 14px 8px;
|
|
9225
|
+
border: none;
|
|
8984
9226
|
background: none;
|
|
8985
9227
|
color: var(--dxr-muted);
|
|
8986
9228
|
font: inherit;
|
|
8987
9229
|
font-size: 12.5px;
|
|
9230
|
+
font-weight: 500;
|
|
8988
9231
|
cursor: pointer;
|
|
9232
|
+
transition: color .15s var(--dxr-ease), box-shadow .15s var(--dxr-ease);
|
|
8989
9233
|
}
|
|
8990
|
-
.dxr-tab:hover { color: var(--dxr-ink);
|
|
9234
|
+
.dxr-tab:hover { color: var(--dxr-ink); }
|
|
8991
9235
|
.dxr-tab[aria-selected="true"] {
|
|
8992
9236
|
color: var(--dxr-ink);
|
|
8993
9237
|
font-weight: 600;
|
|
8994
|
-
|
|
8995
|
-
border-color: var(--dxr-rule);
|
|
8996
|
-
box-shadow: inset 0 2px 0 var(--dxr-accent);
|
|
9238
|
+
box-shadow: inset 0 -2px 0 var(--dxr-accent);
|
|
8997
9239
|
}
|
|
8998
9240
|
/* Contextual tab \u2014 present only while the caret is inside a table. */
|
|
8999
9241
|
.dxr-tab[data-contextual] { color: var(--dxr-accent); }
|
|
@@ -9023,7 +9265,7 @@ var RIBBON_CSS = `
|
|
|
9023
9265
|
.dxr-group:last-child { border-right: none; }
|
|
9024
9266
|
.dxr-group:first-child { padding-left: 0; }
|
|
9025
9267
|
.dxr-glabel {
|
|
9026
|
-
color: var(--dxr-
|
|
9268
|
+
color: var(--dxr-faint);
|
|
9027
9269
|
font-size: 9.5px;
|
|
9028
9270
|
font-weight: 600;
|
|
9029
9271
|
letter-spacing: .11em;
|
|
@@ -9032,48 +9274,69 @@ var RIBBON_CSS = `
|
|
|
9032
9274
|
.dxr-row { display: flex; gap: 3px; align-items: center; }
|
|
9033
9275
|
|
|
9034
9276
|
/* \u2500\u2500 Controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
9277
|
+
/* One button family, house-style: every control is a ghost \u2014 no borders, no
|
|
9278
|
+
fills, no per-button boxes. Hover paints a quiet slate wash; the active
|
|
9279
|
+
(toggled) state paints a teal one. Save alone is the flat primary, so the
|
|
9280
|
+
surface has exactly one accent-colored action. */
|
|
9035
9281
|
.dxr button, .dxr label.dxr-btn {
|
|
9036
9282
|
min-height: var(--dxr-tap);
|
|
9037
9283
|
padding: 5px 9px;
|
|
9038
|
-
border:
|
|
9039
|
-
border-radius:
|
|
9284
|
+
border: none;
|
|
9285
|
+
border-radius: 6px;
|
|
9040
9286
|
background: none;
|
|
9041
9287
|
color: var(--dxr-ink);
|
|
9042
9288
|
font: inherit;
|
|
9043
9289
|
font-size: 13px;
|
|
9290
|
+
font-weight: 500;
|
|
9044
9291
|
line-height: 1.15;
|
|
9045
9292
|
cursor: pointer;
|
|
9293
|
+
transition: background-color .15s var(--dxr-ease), color .15s var(--dxr-ease),
|
|
9294
|
+
box-shadow .15s var(--dxr-ease), transform .15s var(--dxr-ease);
|
|
9046
9295
|
}
|
|
9047
9296
|
.dxr label.dxr-btn { display: inline-flex; align-items: center; }
|
|
9048
|
-
.dxr button:hover, .dxr label.dxr-btn:hover { background: #
|
|
9049
|
-
.dxr button:active { background: #
|
|
9297
|
+
.dxr button:hover, .dxr label.dxr-btn:hover { background: #f1f5f9; }
|
|
9298
|
+
.dxr button:active { background: #e2e8f0; }
|
|
9050
9299
|
.dxr button:disabled { opacity: .38; cursor: default; background: none; }
|
|
9051
|
-
.dxr button.dxr-on { color: var(--dxr-accent); background: var(--dxr-wash);
|
|
9052
|
-
.dxr-quick button, .dxr-quick label.dxr-btn {
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
background:
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
.dxr button
|
|
9300
|
+
.dxr button.dxr-on { color: var(--dxr-accent); background: var(--dxr-wash-on); }
|
|
9301
|
+
.dxr-quick button, .dxr-quick label.dxr-btn { padding: 4px 10px; font-size: 12.5px; }
|
|
9302
|
+
/* Save \u2014 the house primary: flat accent, sm shadow, the 1px lift on hover. */
|
|
9303
|
+
.dxr-quick button[data-dxr="save"]:not(:disabled) {
|
|
9304
|
+
background: var(--dxr-accent);
|
|
9305
|
+
color: #fff;
|
|
9306
|
+
font-weight: 600;
|
|
9307
|
+
box-shadow: var(--dxr-shadow-sm);
|
|
9308
|
+
}
|
|
9309
|
+
.dxr-quick button[data-dxr="save"]:not(:disabled):hover {
|
|
9310
|
+
background: var(--dxr-accent-hover);
|
|
9311
|
+
box-shadow: var(--dxr-shadow-md);
|
|
9312
|
+
transform: translateY(-1px);
|
|
9313
|
+
}
|
|
9314
|
+
.dxr-quick button[data-dxr="save"]:not(:disabled):active {
|
|
9315
|
+
background: var(--dxr-accent-active);
|
|
9316
|
+
box-shadow: var(--dxr-shadow-sm);
|
|
9317
|
+
transform: translateY(0);
|
|
9318
|
+
}
|
|
9319
|
+
/* Icon controls sit quieter than text ones until touched (house IconButton). */
|
|
9320
|
+
.dxr button.dxr-icon { min-width: var(--dxr-tap); text-align: center; color: var(--dxr-muted); }
|
|
9321
|
+
.dxr button.dxr-icon:hover:not(:disabled) { color: var(--dxr-ink); }
|
|
9322
|
+
.dxr button.dxr-icon.dxr-on { color: var(--dxr-accent); }
|
|
9061
9323
|
/* Icons are inline SVG drawn from the same shapes the control acts on (text lines,
|
|
9062
9324
|
rules), so alignment and indent read at a glance instead of relying on arrow
|
|
9063
9325
|
glyphs that collide with undo/redo. currentColor keeps them in step with state. */
|
|
9064
9326
|
.dxr button svg { display: block; margin: 0 auto; fill: currentColor; }
|
|
9065
9327
|
.dxr button.dxr-wide { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
|
|
9066
|
-
.dxr button.dxr-danger:hover { color: var(--dxr-danger); background:
|
|
9328
|
+
.dxr button.dxr-danger:hover { color: var(--dxr-danger); background: var(--dxr-danger-wash); }
|
|
9067
9329
|
.dxr select, .dxr input[type="number"], .dxr input[type="text"] {
|
|
9068
9330
|
min-height: var(--dxr-tap);
|
|
9069
9331
|
padding: 4px 6px;
|
|
9070
9332
|
border: 1px solid var(--dxr-rule);
|
|
9071
|
-
border-radius:
|
|
9072
|
-
background:
|
|
9333
|
+
border-radius: 6px;
|
|
9334
|
+
background: var(--dxr-sheet);
|
|
9073
9335
|
color: var(--dxr-ink);
|
|
9074
9336
|
font: inherit;
|
|
9075
9337
|
font-size: 12.5px;
|
|
9076
9338
|
}
|
|
9339
|
+
.dxr select:hover, .dxr input:hover { border-color: var(--dxr-rule-strong); }
|
|
9077
9340
|
.dxr select:focus-visible, .dxr input:focus-visible, .dxr button:focus-visible,
|
|
9078
9341
|
.dxr .dxr-tab:focus-visible, .dxr label.dxr-btn:focus-within {
|
|
9079
9342
|
outline: 2px solid var(--dxr-accent);
|
|
@@ -9104,7 +9367,7 @@ var RIBBON_CSS = `
|
|
|
9104
9367
|
height: 25px;
|
|
9105
9368
|
padding: 0 10px;
|
|
9106
9369
|
overflow-x: auto;
|
|
9107
|
-
background: #
|
|
9370
|
+
background: #fafafa;
|
|
9108
9371
|
border-top: 1px solid var(--dxr-rule);
|
|
9109
9372
|
color: var(--dxr-muted);
|
|
9110
9373
|
font-family: var(--dxr-mono);
|
|
@@ -9123,7 +9386,7 @@ var RIBBON_CSS = `
|
|
|
9123
9386
|
.dxr-rail .dxr-cell:first-child { padding-left: 0; }
|
|
9124
9387
|
.dxr-rail .dxr-cell:last-child { border-right: none; }
|
|
9125
9388
|
.dxr-rail .dxr-k {
|
|
9126
|
-
color:
|
|
9389
|
+
color: var(--dxr-faint);
|
|
9127
9390
|
font-family: var(--dxr-ui);
|
|
9128
9391
|
font-size: 9.5px;
|
|
9129
9392
|
letter-spacing: .1em;
|
|
@@ -9131,7 +9394,7 @@ var RIBBON_CSS = `
|
|
|
9131
9394
|
}
|
|
9132
9395
|
.dxr-rail .dxr-v { color: var(--dxr-data); }
|
|
9133
9396
|
.dxr-rail .dxr-v.dxr-flash { animation: dxr-railflash .45s ease-out; }
|
|
9134
|
-
@keyframes dxr-railflash { from { background: #
|
|
9397
|
+
@keyframes dxr-railflash { from { background: #ccfbf1; } to { background: transparent; } }
|
|
9135
9398
|
|
|
9136
9399
|
/* \u2500\u2500 Hint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
9137
9400
|
.dxr-hint {
|
|
@@ -9146,8 +9409,8 @@ var RIBBON_CSS = `
|
|
|
9146
9409
|
.dxr-hint kbd {
|
|
9147
9410
|
padding: 0 4px;
|
|
9148
9411
|
border: 1px solid var(--dxr-rule);
|
|
9149
|
-
border-radius:
|
|
9150
|
-
background: #
|
|
9412
|
+
border-radius: 4px;
|
|
9413
|
+
background: #f1f5f9;
|
|
9151
9414
|
font-family: var(--dxr-mono);
|
|
9152
9415
|
font-size: 11px;
|
|
9153
9416
|
}
|
|
@@ -9162,13 +9425,34 @@ var RIBBON_CSS = `
|
|
|
9162
9425
|
SHOULD win.
|
|
9163
9426
|
(No backticks in this file's comments: the stylesheet is a template literal.) */
|
|
9164
9427
|
.dxr-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch; }
|
|
9428
|
+
/* Soft scroll boundaries: content dissolves at the chrome and at the bottom edge
|
|
9429
|
+
instead of hard-clipping. Sticky gradient veils cost one paint layer each and
|
|
9430
|
+
never intercept input. */
|
|
9431
|
+
.dxr-scroll::before, .dxr-scroll::after {
|
|
9432
|
+
content: "";
|
|
9433
|
+
position: sticky;
|
|
9434
|
+
z-index: 3;
|
|
9435
|
+
display: block;
|
|
9436
|
+
height: 26px;
|
|
9437
|
+
pointer-events: none;
|
|
9438
|
+
}
|
|
9439
|
+
.dxr-scroll::before {
|
|
9440
|
+
top: 0;
|
|
9441
|
+
margin-bottom: -26px;
|
|
9442
|
+
background: linear-gradient(to bottom, var(--dxr-desk), transparent);
|
|
9443
|
+
}
|
|
9444
|
+
.dxr-scroll::after {
|
|
9445
|
+
bottom: 0;
|
|
9446
|
+
margin-top: -26px;
|
|
9447
|
+
background: linear-gradient(to top, var(--dxr-desk), transparent);
|
|
9448
|
+
}
|
|
9165
9449
|
.dxr[data-chrome] .dxr-surface { margin: 26px auto; padding: 0 16px 96px; }
|
|
9166
9450
|
.dxr-surface [contenteditable="true"]:focus {
|
|
9167
9451
|
outline: 2px solid var(--dxr-accent);
|
|
9168
9452
|
outline-offset: 2px;
|
|
9169
9453
|
border-radius: 2px;
|
|
9170
9454
|
}
|
|
9171
|
-
@media (hover: hover) { .dxr-surface [contenteditable="true"]:hover { background:
|
|
9455
|
+
@media (hover: hover) { .dxr-surface [contenteditable="true"]:hover { background: var(--dxr-wash); } }
|
|
9172
9456
|
|
|
9173
9457
|
/* Header/footer bands: stories live in their own OOXML parts outside the body,
|
|
9174
9458
|
so they dock as their own regions. Styled from the same tokens as the ribbon
|
|
@@ -9180,9 +9464,10 @@ var RIBBON_CSS = `
|
|
|
9180
9464
|
margin: 0 auto 14px;
|
|
9181
9465
|
padding: 9px 72px 13px;
|
|
9182
9466
|
border: 1px solid var(--dxr-rule);
|
|
9183
|
-
border-left: 2px solid #
|
|
9184
|
-
border-radius:
|
|
9467
|
+
border-left: 2px solid #5eead4;
|
|
9468
|
+
border-radius: 6px;
|
|
9185
9469
|
background: var(--dxr-sheet);
|
|
9470
|
+
box-shadow: var(--dxr-shadow-sm);
|
|
9186
9471
|
}
|
|
9187
9472
|
.dxr-surface .docx-hf-band + .docx-body-flow { margin-top: 0; }
|
|
9188
9473
|
.dxr-surface .docx-hf-band[data-hf-band="footer"] { margin: 14px auto 0; }
|
|
@@ -9201,8 +9486,8 @@ var RIBBON_CSS = `
|
|
|
9201
9486
|
.dxr-surface .docx-hf-chrome select, .dxr-surface .docx-hf-chrome input {
|
|
9202
9487
|
padding: 3px 5px;
|
|
9203
9488
|
border: 1px solid var(--dxr-rule);
|
|
9204
|
-
border-radius:
|
|
9205
|
-
background:
|
|
9489
|
+
border-radius: 6px;
|
|
9490
|
+
background: var(--dxr-sheet);
|
|
9206
9491
|
color: var(--dxr-ink);
|
|
9207
9492
|
font: inherit;
|
|
9208
9493
|
font-family: var(--dxr-ui);
|
|
@@ -9216,22 +9501,22 @@ var RIBBON_CSS = `
|
|
|
9216
9501
|
.dxr-surface .docx-hf-warning {
|
|
9217
9502
|
margin: 0 0 8px -60px;
|
|
9218
9503
|
padding: 7px 9px;
|
|
9219
|
-
border: 1px solid #
|
|
9220
|
-
border-left: 2px solid #
|
|
9221
|
-
border-radius:
|
|
9222
|
-
background: #
|
|
9223
|
-
color: #
|
|
9504
|
+
border: 1px solid #fde68a;
|
|
9505
|
+
border-left: 2px solid #d97706;
|
|
9506
|
+
border-radius: 6px;
|
|
9507
|
+
background: #fffbeb;
|
|
9508
|
+
color: #92400e;
|
|
9224
9509
|
font-size: 12px;
|
|
9225
9510
|
line-height: 1.45;
|
|
9226
9511
|
}
|
|
9227
9512
|
.dxr-surface .docx-hf-warning button {
|
|
9228
9513
|
margin-left: 6px;
|
|
9229
9514
|
padding: 2px 8px;
|
|
9230
|
-
border-color: #
|
|
9515
|
+
border-color: #fde68a;
|
|
9231
9516
|
background: #fff;
|
|
9232
9517
|
font-size: 12px;
|
|
9233
9518
|
}
|
|
9234
|
-
.dxr-surface .docx-hf-placeholder { color:
|
|
9519
|
+
.dxr-surface .docx-hf-placeholder { color: var(--dxr-faint); font-style: italic; }
|
|
9235
9520
|
.dxr-surface .docx-hf-inherited {
|
|
9236
9521
|
color: var(--dxr-muted);
|
|
9237
9522
|
font-style: italic;
|
|
@@ -9251,7 +9536,7 @@ var RIBBON_CSS = `
|
|
|
9251
9536
|
padding: 56px 0;
|
|
9252
9537
|
border-radius: 3px;
|
|
9253
9538
|
background: var(--dxr-sheet);
|
|
9254
|
-
box-shadow: 0 1px 3px rgba(
|
|
9539
|
+
box-shadow: 0 1px 3px rgba(15, 23, 42, .08), 0 12px 24px rgba(15, 23, 42, .06);
|
|
9255
9540
|
}
|
|
9256
9541
|
|
|
9257
9542
|
/* \u2500\u2500 Table size picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
@@ -9261,9 +9546,9 @@ var RIBBON_CSS = `
|
|
|
9261
9546
|
z-index: 30;
|
|
9262
9547
|
padding: 9px;
|
|
9263
9548
|
border: 1px solid var(--dxr-rule);
|
|
9264
|
-
border-radius:
|
|
9549
|
+
border-radius: 12px;
|
|
9265
9550
|
background: #fff;
|
|
9266
|
-
box-shadow:
|
|
9551
|
+
box-shadow: var(--dxr-shadow-xl);
|
|
9267
9552
|
}
|
|
9268
9553
|
.dxr-pop[data-open] { display: block; }
|
|
9269
9554
|
.dxr-gridcells { display: grid; grid-template-columns: repeat(10, 16px); gap: 2px; }
|
|
@@ -9271,11 +9556,11 @@ var RIBBON_CSS = `
|
|
|
9271
9556
|
width: 16px;
|
|
9272
9557
|
height: 16px;
|
|
9273
9558
|
border: 1px solid var(--dxr-rule);
|
|
9274
|
-
border-radius:
|
|
9275
|
-
background:
|
|
9559
|
+
border-radius: 3px;
|
|
9560
|
+
background: var(--dxr-chrome-sunk);
|
|
9276
9561
|
cursor: pointer;
|
|
9277
9562
|
}
|
|
9278
|
-
.dxr-gridcells div[data-on] { background:
|
|
9563
|
+
.dxr-gridcells div[data-on] { background: #ccfbf1; border-color: var(--dxr-accent); }
|
|
9279
9564
|
.dxr-popfoot {
|
|
9280
9565
|
display: flex;
|
|
9281
9566
|
justify-content: space-between;
|
|
@@ -9358,11 +9643,11 @@ var RIBBON_CSS = `
|
|
|
9358
9643
|
display: grid;
|
|
9359
9644
|
place-items: center;
|
|
9360
9645
|
padding: 24px;
|
|
9361
|
-
color: #
|
|
9646
|
+
color: #f8fafc;
|
|
9362
9647
|
background:
|
|
9363
|
-
radial-gradient(circle at 20% 20%, rgba(
|
|
9364
|
-
radial-gradient(circle at 82% 80%, rgba(
|
|
9365
|
-
linear-gradient(
|
|
9648
|
+
radial-gradient(circle at 20% 20%, rgba(13, 148, 136, .2), transparent 22rem),
|
|
9649
|
+
radial-gradient(circle at 82% 80%, rgba(45, 212, 191, .1), transparent 24rem),
|
|
9650
|
+
linear-gradient(150deg, #0b1220 0%, #0f172a 55%, #0f2723 100%);
|
|
9366
9651
|
transition: opacity .55s ease, visibility .55s ease;
|
|
9367
9652
|
}
|
|
9368
9653
|
.dxr-loader[hidden] { display: none; }
|
|
@@ -9381,14 +9666,14 @@ var RIBBON_CSS = `
|
|
|
9381
9666
|
.dxr-orbit {
|
|
9382
9667
|
position: absolute;
|
|
9383
9668
|
inset: 7%;
|
|
9384
|
-
border: 1px solid rgba(
|
|
9669
|
+
border: 1px solid rgba(45, 212, 191, .24);
|
|
9385
9670
|
border-radius: 50%;
|
|
9386
9671
|
animation: dxr-spin 9s linear infinite;
|
|
9387
9672
|
}
|
|
9388
9673
|
.dxr-orbit.dxr-two {
|
|
9389
9674
|
inset: 20%;
|
|
9390
9675
|
border-style: dashed;
|
|
9391
|
-
border-color: rgba(
|
|
9676
|
+
border-color: rgba(94, 234, 212, .3);
|
|
9392
9677
|
animation-duration: 6s;
|
|
9393
9678
|
animation-direction: reverse;
|
|
9394
9679
|
}
|
|
@@ -9398,19 +9683,19 @@ var RIBBON_CSS = `
|
|
|
9398
9683
|
height: 10px;
|
|
9399
9684
|
border-radius: 50%;
|
|
9400
9685
|
content: "";
|
|
9401
|
-
background: #
|
|
9402
|
-
box-shadow: 0 0 18px
|
|
9686
|
+
background: #2dd4bf;
|
|
9687
|
+
box-shadow: 0 0 18px rgba(45, 212, 191, .8);
|
|
9403
9688
|
}
|
|
9404
9689
|
.dxr-orbit::before { top: -5px; left: 50%; }
|
|
9405
|
-
.dxr-orbit::after { right: 7%; bottom: 12%; background: #
|
|
9690
|
+
.dxr-orbit::after { right: 7%; bottom: 12%; background: #5eead4; box-shadow: 0 0 18px rgba(94, 234, 212, .7); }
|
|
9406
9691
|
.dxr-card {
|
|
9407
9692
|
position: absolute;
|
|
9408
9693
|
inset: 24% 28%;
|
|
9409
9694
|
padding: 20px 15px;
|
|
9410
|
-
border: 1px solid rgba(255, 255, 255, .
|
|
9695
|
+
border: 1px solid rgba(255, 255, 255, .3);
|
|
9411
9696
|
border-radius: 14px;
|
|
9412
|
-
background: linear-gradient(150deg, rgba(255, 255, 255, .
|
|
9413
|
-
box-shadow: 0 22px 50px rgba(0, 0, 0, .35), 0 0 45px rgba(
|
|
9697
|
+
background: linear-gradient(150deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .05));
|
|
9698
|
+
box-shadow: 0 22px 50px rgba(0, 0, 0, .35), 0 0 45px rgba(13, 148, 136, .15);
|
|
9414
9699
|
backdrop-filter: blur(10px);
|
|
9415
9700
|
animation: dxr-float 3.6s ease-in-out infinite;
|
|
9416
9701
|
}
|
|
@@ -9420,8 +9705,8 @@ var RIBBON_CSS = `
|
|
|
9420
9705
|
right: -9px;
|
|
9421
9706
|
padding: 4px 7px;
|
|
9422
9707
|
border-radius: 6px;
|
|
9423
|
-
background: #
|
|
9424
|
-
color: #
|
|
9708
|
+
background: #2dd4bf;
|
|
9709
|
+
color: #042f2e;
|
|
9425
9710
|
content: "DOCX";
|
|
9426
9711
|
font-size: 8px;
|
|
9427
9712
|
font-weight: 900;
|
|
@@ -9438,46 +9723,49 @@ var RIBBON_CSS = `
|
|
|
9438
9723
|
}
|
|
9439
9724
|
.dxr-card i:nth-child(2) { width: 76%; animation-delay: -.45s; }
|
|
9440
9725
|
.dxr-card i:nth-child(3) { width: 88%; animation-delay: -.85s; }
|
|
9441
|
-
.dxr-card i:nth-child(4) { width: 58%; background: rgba(
|
|
9726
|
+
.dxr-card i:nth-child(4) { width: 58%; background: rgba(248, 113, 113, .75); animation-delay: -1.2s; }
|
|
9442
9727
|
.dxr-chip {
|
|
9443
9728
|
position: absolute;
|
|
9444
9729
|
display: grid;
|
|
9445
9730
|
width: 34px;
|
|
9446
9731
|
height: 34px;
|
|
9447
9732
|
place-items: center;
|
|
9448
|
-
border: 1px solid rgba(255, 255, 255, .
|
|
9733
|
+
border: 1px solid rgba(255, 255, 255, .16);
|
|
9449
9734
|
border-radius: 11px;
|
|
9450
|
-
background: rgba(
|
|
9735
|
+
background: rgba(15, 30, 46, .88);
|
|
9451
9736
|
box-shadow: 0 12px 30px rgba(0, 0, 0, .28);
|
|
9452
9737
|
font-size: 11px;
|
|
9453
9738
|
font-weight: 850;
|
|
9454
9739
|
}
|
|
9455
|
-
.dxr-chip.dxr-b { left: 2%; top: 30%; color: #
|
|
9456
|
-
.dxr-chip.dxr-r { right: -2%; bottom: 24%; color: #
|
|
9457
|
-
.dxr-chip.dxr-s { left: 20%; bottom: 0; color: #
|
|
9458
|
-
.dxr-eyebrow { color: #
|
|
9740
|
+
.dxr-chip.dxr-b { left: 2%; top: 30%; color: #5eead4; animation: dxr-chip 3s ease-in-out infinite; }
|
|
9741
|
+
.dxr-chip.dxr-r { right: -2%; bottom: 24%; color: #fca5a5; animation: dxr-chip 3s -1.4s ease-in-out infinite; }
|
|
9742
|
+
.dxr-chip.dxr-s { left: 20%; bottom: 0; color: #6ee7b7; animation: dxr-chip 3s -.7s ease-in-out infinite; }
|
|
9743
|
+
.dxr-eyebrow { color: #5eead4; font-size: 10px; font-weight: 850; letter-spacing: .16em; text-transform: uppercase; }
|
|
9744
|
+
/* Georgia headline \u2014 the house pairing of a serif headline over Inter UI copy. */
|
|
9459
9745
|
.dxr-loader h2 {
|
|
9460
9746
|
margin: 10px auto 10px;
|
|
9461
9747
|
max-width: 520px;
|
|
9462
|
-
font-
|
|
9463
|
-
|
|
9464
|
-
|
|
9748
|
+
font-family: var(--dxr-serif);
|
|
9749
|
+
font-size: clamp(23px, 5vw, 38px);
|
|
9750
|
+
font-weight: 500;
|
|
9751
|
+
line-height: 1.08;
|
|
9752
|
+
letter-spacing: -.02em;
|
|
9465
9753
|
}
|
|
9466
|
-
.dxr-loader-copy > p { margin: 0 auto; max-width: 46ch; color: #
|
|
9754
|
+
.dxr-loader-copy > p { margin: 0 auto; max-width: 46ch; color: #94a3b8; font-size: 13.5px; line-height: 1.6; }
|
|
9467
9755
|
.dxr-ad {
|
|
9468
9756
|
display: flex;
|
|
9469
9757
|
gap: 12px;
|
|
9470
9758
|
margin: 20px auto 0;
|
|
9471
9759
|
max-width: 420px;
|
|
9472
9760
|
padding: 13px;
|
|
9473
|
-
border: 1px solid rgba(
|
|
9474
|
-
border-radius:
|
|
9761
|
+
border: 1px solid rgba(148, 163, 184, .16);
|
|
9762
|
+
border-radius: 12px;
|
|
9475
9763
|
background: rgba(255, 255, 255, .04);
|
|
9476
9764
|
text-align: left;
|
|
9477
9765
|
}
|
|
9478
|
-
.dxr-ad .dxr-num { color: #
|
|
9766
|
+
.dxr-ad .dxr-num { color: #2dd4bf; font: 800 10px/1.4 var(--dxr-mono); }
|
|
9479
9767
|
.dxr-ad strong { display: block; font-size: 12.5px; }
|
|
9480
|
-
.dxr-ad .dxr-adcopy { display: block; margin-top: 4px; color: #
|
|
9768
|
+
.dxr-ad .dxr-adcopy { display: block; margin-top: 4px; color: #8ba0b9; font-size: 11.5px; line-height: 1.45; }
|
|
9481
9769
|
.dxr-ad[data-swap] { animation: dxr-swap .4s ease; }
|
|
9482
9770
|
.dxr-track {
|
|
9483
9771
|
height: 3px;
|
|
@@ -9491,8 +9779,8 @@ var RIBBON_CSS = `
|
|
|
9491
9779
|
width: 12%;
|
|
9492
9780
|
height: 100%;
|
|
9493
9781
|
border-radius: inherit;
|
|
9494
|
-
background: linear-gradient(90deg, #
|
|
9495
|
-
box-shadow: 0 0 16px rgba(
|
|
9782
|
+
background: linear-gradient(90deg, #14b8a6, #2dd4bf, #5eead4);
|
|
9783
|
+
box-shadow: 0 0 16px rgba(45, 212, 191, .5);
|
|
9496
9784
|
transition: width .65s cubic-bezier(.22, .8, .28, 1);
|
|
9497
9785
|
}
|
|
9498
9786
|
.dxr-meta {
|
|
@@ -9501,7 +9789,7 @@ var RIBBON_CSS = `
|
|
|
9501
9789
|
gap: 14px;
|
|
9502
9790
|
margin: 9px auto 0;
|
|
9503
9791
|
max-width: 420px;
|
|
9504
|
-
color: #
|
|
9792
|
+
color: #64748b;
|
|
9505
9793
|
font: 700 9px/1 var(--dxr-mono);
|
|
9506
9794
|
letter-spacing: .09em;
|
|
9507
9795
|
text-transform: uppercase;
|
|
@@ -9510,9 +9798,9 @@ var RIBBON_CSS = `
|
|
|
9510
9798
|
display: none;
|
|
9511
9799
|
margin-top: 18px;
|
|
9512
9800
|
padding: 9px 14px;
|
|
9513
|
-
border: 1px solid rgba(
|
|
9801
|
+
border: 1px solid rgba(248, 113, 113, .4);
|
|
9514
9802
|
border-radius: 9px;
|
|
9515
|
-
background: rgba(
|
|
9803
|
+
background: rgba(248, 113, 113, .12);
|
|
9516
9804
|
color: #fff;
|
|
9517
9805
|
cursor: pointer;
|
|
9518
9806
|
}
|
|
@@ -9627,8 +9915,8 @@ var RIBBON_HTML = `
|
|
|
9627
9915
|
)}</button>
|
|
9628
9916
|
</div>
|
|
9629
9917
|
<div class="dxr-row">
|
|
9630
|
-
<button type="button" data-list="bullet" title="Bullet list"
|
|
9631
|
-
<button type="button" data-list="decimal" title="Numbered list">
|
|
9918
|
+
<button type="button" data-list="bullet" title="Bullet list">Bullets</button>
|
|
9919
|
+
<button type="button" data-list="decimal" title="Numbered list">Numbered</button>
|
|
9632
9920
|
<button type="button" data-pagebreak title="Start this block on a new page">Page break</button>
|
|
9633
9921
|
</div>
|
|
9634
9922
|
</div>
|
|
@@ -9951,6 +10239,7 @@ var RibbonSurface = class {
|
|
|
9951
10239
|
const root = doc.createElement("div");
|
|
9952
10240
|
root.className = "dxr";
|
|
9953
10241
|
root.dataset.state = "idle";
|
|
10242
|
+
root.dataset.frame = this.options.frame ?? "flush";
|
|
9954
10243
|
root.innerHTML = RIBBON_HTML;
|
|
9955
10244
|
for (const el of Array.from(root.querySelectorAll("[data-dxr]"))) {
|
|
9956
10245
|
el.id = this.idPrefix + el.dataset.dxr;
|
|
@@ -12018,6 +12307,9 @@ async function createRibbonEditor(container, source, options = {}) {
|
|
|
12018
12307
|
mount2.root.style.minHeight = "0";
|
|
12019
12308
|
const ribbon = mountRibbon(mount2.root, {
|
|
12020
12309
|
documentName: ribbonOptions.documentName ?? nameFromSource(source),
|
|
12310
|
+
// A drop-in embed sits in the middle of someone's page, so it carries its own
|
|
12311
|
+
// boundary (rounded card + shadow). Full-bleed hosts pass frame: "flush".
|
|
12312
|
+
frame: "card",
|
|
12021
12313
|
...ribbonOptions,
|
|
12022
12314
|
// Exports arrive after the runtime boots; the loader covers that gap.
|
|
12023
12315
|
exports: void 0
|