wordinweb 0.1.9 → 0.1.10
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/README.md +43 -0
- package/dist/index.d.ts +28 -2
- package/dist/index.js +1261 -209
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3955,10 +3955,12 @@ function parseRun(r, ctx, field, suppressedObjects) {
|
|
|
3955
3955
|
case "endnoteReference": {
|
|
3956
3956
|
const id = intAttr(el16, "id");
|
|
3957
3957
|
if (id !== void 0) {
|
|
3958
|
+
const customMark = attr(el16, "customMarkFollows");
|
|
3958
3959
|
run.content.push({
|
|
3959
3960
|
kind: "noteRef",
|
|
3960
3961
|
noteType: ln === "footnoteReference" ? "footnote" : "endnote",
|
|
3961
|
-
id
|
|
3962
|
+
id,
|
|
3963
|
+
customMarkFollows: customMark !== void 0 && customMark !== "0" && customMark !== "false" && customMark !== "off"
|
|
3962
3964
|
});
|
|
3963
3965
|
}
|
|
3964
3966
|
break;
|
|
@@ -4361,6 +4363,7 @@ function parseDrawing(drawing, ctx) {
|
|
|
4361
4363
|
const rot = intAttr(xfrm, "rot");
|
|
4362
4364
|
const lnEl = child(spPr, "ln");
|
|
4363
4365
|
const strokeColor = lnEl && !child(lnEl, "noFill") ? fillColorOf(lnEl) : void 0;
|
|
4366
|
+
const fill = child(spPr, "noFill") ? void 0 : fillColorOf(spPr) ?? styleFillOf(textboxEl);
|
|
4364
4367
|
const bodyPr = child(textboxEl, "bodyPr");
|
|
4365
4368
|
const insetOf = (name, dflt) => {
|
|
4366
4369
|
const v = bodyPr ? intAttr(bodyPr, name) : void 0;
|
|
@@ -4404,7 +4407,7 @@ function parseDrawing(drawing, ctx) {
|
|
|
4404
4407
|
vAlign: vAlignOf(posV),
|
|
4405
4408
|
blocks: txbxContent ? parseBlocks(txbxContent, ctx) : [],
|
|
4406
4409
|
...textboxChainId !== void 0 ? { chainId: textboxChainId, chainSeq: textboxChainSeq ?? 0 } : {},
|
|
4407
|
-
...
|
|
4410
|
+
...fill ? { fill } : {},
|
|
4408
4411
|
...strokeColor ? { stroke: { color: strokeColor, weight: Math.max(emuToPx(intAttr(lnEl, "w") ?? 0), 0.75) } } : {},
|
|
4409
4412
|
textAnchor: anchorAttr === "ctr" ? "middle" : anchorAttr === "b" ? "bottom" : anchorAttr === "t" ? "top" : void 0,
|
|
4410
4413
|
insets: {
|
|
@@ -8092,7 +8095,10 @@ var WORD_FONT_METRICS = {
|
|
|
8092
8095
|
// baselines 118.80 + n x 20.00; first attempt baked the multiple into the
|
|
8093
8096
|
// profile and over-pitched every line by 1.08x).
|
|
8094
8097
|
mangal: { asc: 1.245, desc: 0.4399, gap: 0 },
|
|
8095
|
-
latha: { asc: 0.9266, desc: 0.3369, gap: 0 }
|
|
8098
|
+
latha: { asc: 0.9266, desc: 0.3369, gap: 0 },
|
|
8099
|
+
// Word substitutes Lao text to DokChampa. Its hhea box is 2850/-1117 at
|
|
8100
|
+
// 2048 UPEM; this is also the line profile Word uses in the reference PDF.
|
|
8101
|
+
"noto sans lao looped": { asc: 1.391602, desc: 0.54541, gap: 0 }
|
|
8096
8102
|
};
|
|
8097
8103
|
var QUARTER_PT_PX = 1 / 3;
|
|
8098
8104
|
function quantizeQuarterPt(px) {
|
|
@@ -9184,6 +9190,7 @@ var JUSTIFY_MAX_COMPRESS = 0.25;
|
|
|
9184
9190
|
var JUSTIFY_STRETCH_FACTOR = 0.5;
|
|
9185
9191
|
var TAMIL_GLYPH_SCALE = 0.735;
|
|
9186
9192
|
var TAMIL_BASELINE_DY_EM = 0.136;
|
|
9193
|
+
var LAO_GLYPH_SCALE = 1.048;
|
|
9187
9194
|
var KASHIDA_LOW_EM = 0;
|
|
9188
9195
|
var KASHIDA_MEDIUM_EM = 0.032;
|
|
9189
9196
|
var KASHIDA_HIGH_EM = 0.04;
|
|
@@ -9538,6 +9545,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9538
9545
|
href: atom.href,
|
|
9539
9546
|
src: atom.src ? { ...atom.src, offset: atom.src.offset + sliceOff } : void 0,
|
|
9540
9547
|
metricsFont: atom.metricsFont,
|
|
9548
|
+
metricsStrut: atom.metricsStrut,
|
|
9541
9549
|
rtl: atom.rtl,
|
|
9542
9550
|
rtlLevel: levelOf(atom.rtl)
|
|
9543
9551
|
});
|
|
@@ -9661,6 +9669,44 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9661
9669
|
if (found) target = stop.pos - pre;
|
|
9662
9670
|
}
|
|
9663
9671
|
}
|
|
9672
|
+
if (doc.compatibilityMode < 15 && stop.align === "left" && !bidiPara && curLineWidth > 0) {
|
|
9673
|
+
let nextAtom = ai + 1;
|
|
9674
|
+
let probeX = Math.max(target, x + 2);
|
|
9675
|
+
while (atoms[nextAtom]?.kind === "tab") {
|
|
9676
|
+
let probeStop = nextTabStop(
|
|
9677
|
+
probeX + offset,
|
|
9678
|
+
props.tabs,
|
|
9679
|
+
contentWidth - indentRight,
|
|
9680
|
+
doc.defaultTabStop
|
|
9681
|
+
);
|
|
9682
|
+
if (opts?.inTableCell) {
|
|
9683
|
+
let guard = 0;
|
|
9684
|
+
while (probeStop.align === "decimal" && guard++ < 8) {
|
|
9685
|
+
probeStop = nextTabStop(
|
|
9686
|
+
probeStop.pos,
|
|
9687
|
+
props.tabs,
|
|
9688
|
+
contentWidth - indentRight,
|
|
9689
|
+
doc.defaultTabStop
|
|
9690
|
+
);
|
|
9691
|
+
}
|
|
9692
|
+
}
|
|
9693
|
+
if (probeStop.align !== "left") break;
|
|
9694
|
+
probeX = Math.max(probeStop.pos - offset, probeX + 2);
|
|
9695
|
+
nextAtom++;
|
|
9696
|
+
}
|
|
9697
|
+
let firstWordWidth = 0;
|
|
9698
|
+
for (let j = nextAtom; j < atoms.length; j++) {
|
|
9699
|
+
const a = atoms[j];
|
|
9700
|
+
if (a.kind !== "frag") break;
|
|
9701
|
+
firstWordWidth += a.width;
|
|
9702
|
+
}
|
|
9703
|
+
const lineEnd2 = lineStartX(lineIndex) + availFor(lineIndex);
|
|
9704
|
+
if (firstWordWidth > 0 && probeX + firstWordWidth > lineEnd2 + 0.01) {
|
|
9705
|
+
flush(false, false);
|
|
9706
|
+
ai--;
|
|
9707
|
+
continue;
|
|
9708
|
+
}
|
|
9709
|
+
}
|
|
9664
9710
|
const aligned = (stop.align === "right" || stop.align === "decimal") && !bidiPara;
|
|
9665
9711
|
if (aligned && curLineWidth > 0 && x > target + 0.75) {
|
|
9666
9712
|
flush(false, false);
|
|
@@ -9926,7 +9972,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9926
9972
|
}
|
|
9927
9973
|
const padL = bdrPad && (!sameBdrAtom(atoms[ai - 1], atom) || curLineWidth === 0) ? bdrPad : 0;
|
|
9928
9974
|
x += padL;
|
|
9929
|
-
cur.push({ x, width: atom.width, text: atom.text, props: atom.props, font: atom.font, href: atom.href, src: atom.src, noteId: atom.noteId, metricsFont: atom.metricsFont, breakAfter: atom.breakAfter, pageRef: atom.pageRef, rtl: atom.rtl, rtlLevel: levelOf(atom.rtl), ruby: atom.ruby });
|
|
9975
|
+
cur.push({ x, width: atom.width, text: atom.text, props: atom.props, font: atom.font, href: atom.href, src: atom.src, noteId: atom.noteId, metricsFont: atom.metricsFont, metricsStrut: atom.metricsStrut, breakAfter: atom.breakAfter, pageRef: atom.pageRef, rtl: atom.rtl, rtlLevel: levelOf(atom.rtl), ruby: atom.ruby });
|
|
9930
9976
|
curLineWidth += padL + atom.width + bdrPadR;
|
|
9931
9977
|
x += atom.width + bdrPadR;
|
|
9932
9978
|
if (atom.text.trim().length > 0) prevContentCJK = fragIsCJK;
|
|
@@ -10083,6 +10129,7 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10083
10129
|
let maxBorderedAscent = 0;
|
|
10084
10130
|
let maxBorderedDescent = 0;
|
|
10085
10131
|
let tallestTextIsEa = false;
|
|
10132
|
+
let metricsStrutHeight = 0;
|
|
10086
10133
|
const consider = (font, imageHeight, objRaise = 0, descShift = 0) => {
|
|
10087
10134
|
if (imageHeight !== void 0) {
|
|
10088
10135
|
maxAscent = Math.max(maxAscent, imageHeight + objRaise);
|
|
@@ -10123,7 +10170,7 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10123
10170
|
};
|
|
10124
10171
|
let metricSpans = spans.filter((s) => !(s.text === " " && !s.leader));
|
|
10125
10172
|
const solidSpans = metricSpans.filter(
|
|
10126
|
-
(s) => s.image || s.drawing || s.math || s.leader || s.text === void 0 || !/^[ \t]*$/.test(s.text)
|
|
10173
|
+
(s) => s.metricsStrut || s.image || s.drawing || s.math || s.leader || s.text === void 0 || !/^[ \t]*$/.test(s.text)
|
|
10127
10174
|
);
|
|
10128
10175
|
if (solidSpans.length > 0) metricSpans = solidSpans;
|
|
10129
10176
|
if (metricSpans.some((s) => s.numLabel) && metricSpans.some((s) => !s.numLabel)) {
|
|
@@ -10156,7 +10203,13 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10156
10203
|
const lineHasObject = metricSpans.some((s) => s.image || s.drawing);
|
|
10157
10204
|
for (const s of metricSpans) {
|
|
10158
10205
|
let textMetrics;
|
|
10159
|
-
if (s.
|
|
10206
|
+
if (s.metricsStrut) {
|
|
10207
|
+
metricsStrutHeight = Math.max(
|
|
10208
|
+
metricsStrutHeight,
|
|
10209
|
+
measurer.metrics(s.metricsFont ?? s.font).lineHeight
|
|
10210
|
+
);
|
|
10211
|
+
consider(s.metricsFont ?? s.font);
|
|
10212
|
+
} else if (s.image || s.drawing) {
|
|
10160
10213
|
const objectMetrics = measurer.metrics(s.metricsFont ?? s.font);
|
|
10161
10214
|
const objectHeight = s.image?.height ?? s.drawing.height;
|
|
10162
10215
|
const objRaise = s.props.raise ?? 0;
|
|
@@ -10211,6 +10264,14 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10211
10264
|
const commonLower = metricSpans.length > 0 && metricSpans.every(
|
|
10212
10265
|
(s) => !s.image && !s.drawing && !s.math && (s.props.raise ?? 0) < 0
|
|
10213
10266
|
) ? Math.min(...metricSpans.map((s) => -s.props.raise)) : 0;
|
|
10267
|
+
if (metricsStrutHeight > 0) {
|
|
10268
|
+
for (const s of spans) {
|
|
10269
|
+
if (s.metricsStrut || s.image || s.drawing || s.math) continue;
|
|
10270
|
+
const spanHeight = measurer.metrics(s.font).lineHeight;
|
|
10271
|
+
const paintDY = Math.max(0, (metricsStrutHeight - spanHeight) / 2);
|
|
10272
|
+
if (paintDY > 0) s.font = { ...s.font, paintDY: (s.font.paintDY ?? 0) + paintDY };
|
|
10273
|
+
}
|
|
10274
|
+
}
|
|
10214
10275
|
const natural = Math.max(maxNatural, maxAscent + maxDescent, minLineHeight ?? 0);
|
|
10215
10276
|
let height = natural;
|
|
10216
10277
|
let baselineH;
|
|
@@ -10371,11 +10432,22 @@ function resolveBidiRtl(text) {
|
|
|
10371
10432
|
function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
10372
10433
|
const atoms = [];
|
|
10373
10434
|
const anchors = [];
|
|
10435
|
+
const stylelessOleParagraph = doc.styles.defaultRPr.font === void 0 && doc.styles.defaultRPr.size === void 0 && para.children.some((child4) => {
|
|
10436
|
+
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
10437
|
+
return runs.some(
|
|
10438
|
+
(run) => run.content.some(
|
|
10439
|
+
(content) => content.kind === "image" && content.embeddedObject !== void 0
|
|
10440
|
+
)
|
|
10441
|
+
);
|
|
10442
|
+
});
|
|
10374
10443
|
const bidiPara = doc.effectiveParaProps(para).bidi === true;
|
|
10375
10444
|
const kashidaKind = doc.effectiveParaProps(para).justifyKind;
|
|
10376
10445
|
const kashidaEm = kashidaKind === "highKashida" ? KASHIDA_HIGH_EM : kashidaKind === "mediumKashida" ? KASHIDA_MEDIUM_EM : kashidaKind === "lowKashida" ? KASHIDA_LOW_EM : 0;
|
|
10377
10446
|
const pushRun = (run, href) => {
|
|
10378
|
-
|
|
10447
|
+
let baseProps = doc.effectiveRunProps(para, run.props);
|
|
10448
|
+
if (stylelessOleParagraph && baseProps.size === void 0) {
|
|
10449
|
+
baseProps = { ...baseProps, size: 16 };
|
|
10450
|
+
}
|
|
10379
10451
|
if (baseProps.vanish) return;
|
|
10380
10452
|
const font = fontOf(baseProps, fallbackFamily);
|
|
10381
10453
|
let props = kashidaEm > 0 && baseProps.rtl ? { ...baseProps, letterSpacing: (baseProps.letterSpacing ?? 0) + kashidaEm * font.size } : baseProps;
|
|
@@ -10445,6 +10517,20 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10445
10517
|
});
|
|
10446
10518
|
break;
|
|
10447
10519
|
}
|
|
10520
|
+
if (!text && /^\s*SEQ\b/i.test(content.instruction) && /\\h(\s|$)/i.test(content.instruction)) {
|
|
10521
|
+
atoms.push({
|
|
10522
|
+
kind: "frag",
|
|
10523
|
+
text: "",
|
|
10524
|
+
props,
|
|
10525
|
+
font,
|
|
10526
|
+
width: 0,
|
|
10527
|
+
href,
|
|
10528
|
+
src: { run, t: null, offset: 0 },
|
|
10529
|
+
metricsFont: vertMetricsFont,
|
|
10530
|
+
metricsStrut: true
|
|
10531
|
+
});
|
|
10532
|
+
break;
|
|
10533
|
+
}
|
|
10448
10534
|
if (text) pushStyled(displayText(text, props), props, font, href, { run, t: null, offset: 0 }, vertMetricsFont);
|
|
10449
10535
|
break;
|
|
10450
10536
|
}
|
|
@@ -10489,7 +10575,7 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10489
10575
|
break;
|
|
10490
10576
|
}
|
|
10491
10577
|
case "noteRef": {
|
|
10492
|
-
const text = content.self ? fields.selfNoteMark?.() ?? "" : fields.noteMark?.(content.noteType, content.id) ?? "";
|
|
10578
|
+
const text = content.self ? fields.selfNoteMark?.() ?? "" : content.customMarkFollows ? "" : fields.noteMark?.(content.noteType, content.id) ?? "";
|
|
10493
10579
|
if (!text) break;
|
|
10494
10580
|
const markProps = props.verticalAlign ? props : { ...props, verticalAlign: "superscript" };
|
|
10495
10581
|
const markFont = fontOf(markProps, fallbackFamily);
|
|
@@ -10545,6 +10631,7 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10545
10631
|
const hasLao = /[-]/.test(text);
|
|
10546
10632
|
const indicFace = hasDeva && !hasTamil && !hasLao ? "Mangal" : hasTamil && !hasDeva && !hasLao ? "Latha" : hasLao && !hasDeva && !hasTamil ? "Noto Sans Lao Looped" : null;
|
|
10547
10633
|
if (indicFace && font.family.toLowerCase() !== indicFace.toLowerCase()) {
|
|
10634
|
+
const scriptProps = indicFace === "Noto Sans Lao Looped" ? { ...props, textScale: (props.textScale ?? 1) * LAO_GLYPH_SCALE } : props;
|
|
10548
10635
|
const indicScale = indicFace === "Latha" ? TAMIL_GLYPH_SCALE : 1;
|
|
10549
10636
|
const indicFont = indicScale === 1 ? { ...font, family: indicFace } : {
|
|
10550
10637
|
...font,
|
|
@@ -10564,7 +10651,7 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10564
10651
|
const seg = text.slice(i2, j);
|
|
10565
10652
|
const src = srcBase ? { ...srcBase, offset: srcBase.offset + i2 } : void 0;
|
|
10566
10653
|
if (isSpace) pushText(seg, props, font, href, src, metricsFont);
|
|
10567
|
-
else pushText(seg,
|
|
10654
|
+
else pushText(seg, scriptProps, indicFont, href, src, indicMetrics);
|
|
10568
10655
|
i2 = j;
|
|
10569
10656
|
}
|
|
10570
10657
|
return;
|
|
@@ -10787,8 +10874,8 @@ function resolveField(instruction, cachedResult, ctx, fieldKey) {
|
|
|
10787
10874
|
}
|
|
10788
10875
|
case "SEQ": {
|
|
10789
10876
|
const ident = instr.split(/\s+/)[1];
|
|
10790
|
-
|
|
10791
|
-
return
|
|
10877
|
+
const value = ident && ctx.seq && fieldKey ? ctx.seq(ident, fieldKey, instr) : cachedResult || "";
|
|
10878
|
+
return /\\h(\s|$)/i.test(instr) ? "" : value;
|
|
10792
10879
|
}
|
|
10793
10880
|
case "REF": {
|
|
10794
10881
|
const bookmark = instr.split(/\s+/)[1];
|
|
@@ -11011,6 +11098,7 @@ var MULTI_COL_NOTE_SEP_RESERVE = 26;
|
|
|
11011
11098
|
var NOTE_SEP_LEN = 192;
|
|
11012
11099
|
var NOTE_SEP_GAP = 4.4;
|
|
11013
11100
|
var ROW_OVERHANG_TOL = 3;
|
|
11101
|
+
var CUSTOM_NOTE_BANNER_OVERHANG = 3;
|
|
11014
11102
|
var CHICAGO = ["*", "\u2020", "\u2021", "\xA7"];
|
|
11015
11103
|
var AUTO_PARA_SPACING_PX = 14 * (96 / 72);
|
|
11016
11104
|
var FRAME_WRAP_HSPACE_PX = 6 * (96 / 72);
|
|
@@ -11118,6 +11206,7 @@ var Engine = class {
|
|
|
11118
11206
|
/** Vertical flow already consumed in the current later-column pre-banner
|
|
11119
11207
|
* slot. It reduces the below-banner capacity by the same amount. */
|
|
11120
11208
|
this.bannerSlotUsed = 0;
|
|
11209
|
+
this.customNoteBannerFit = false;
|
|
11121
11210
|
/** True while a section-level tbRl vertical flow is being laid: paragraphs
|
|
11122
11211
|
* re-establish the vertical grid after embedded Western runs (see
|
|
11123
11212
|
* breakParagraph's verticalGridResync). */
|
|
@@ -11235,7 +11324,7 @@ var Engine = class {
|
|
|
11235
11324
|
const contentWidth = page.sp.pageWidth - page.sp.marginLeft - page.sp.marginRight - page.sp.gutter;
|
|
11236
11325
|
const header = this.doc.headers.get(page.headerRel ?? "");
|
|
11237
11326
|
const footer = this.doc.footers.get(page.footerRel ?? "");
|
|
11238
|
-
const headerHeight = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header));
|
|
11327
|
+
const headerHeight = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header), true);
|
|
11239
11328
|
const footerHeight = this.measureHeaderFooter(footer, page, contentWidth, this.pageFieldFrameOverlay(footer));
|
|
11240
11329
|
if (headerHeight !== page.headerHeight || footerHeight !== page.footerHeight) return null;
|
|
11241
11330
|
}
|
|
@@ -11335,6 +11424,7 @@ var Engine = class {
|
|
|
11335
11424
|
if (this.pages.length === 0) {
|
|
11336
11425
|
this.sp = sections[0]?.props ?? {};
|
|
11337
11426
|
}
|
|
11427
|
+
this.applyOpeningFlowOverlap();
|
|
11338
11428
|
this.placeEndnotes();
|
|
11339
11429
|
this.emitFootnoteAreas();
|
|
11340
11430
|
this.emitColumnSeparators();
|
|
@@ -11363,6 +11453,43 @@ var Engine = class {
|
|
|
11363
11453
|
}
|
|
11364
11454
|
return result;
|
|
11365
11455
|
}
|
|
11456
|
+
/** Some document-opening empty paragraphs reserve a second mark line for
|
|
11457
|
+
* pagination while the following content paints over it on page one. Keep
|
|
11458
|
+
* the reservation in flow so later page breaks stay unchanged, then lift
|
|
11459
|
+
* only the painted first-page body. */
|
|
11460
|
+
applyOpeningFlowOverlap() {
|
|
11461
|
+
const opening = this.doc.sections[0]?.blocks[0];
|
|
11462
|
+
const next = this.doc.sections[0]?.blocks[1];
|
|
11463
|
+
const page = this.pages[0];
|
|
11464
|
+
if (!page || page.openingFlowOverlapApplied || opening?.type !== "paragraph" || opening.sectionBreak || paragraphHasContent(opening)) {
|
|
11465
|
+
return;
|
|
11466
|
+
}
|
|
11467
|
+
const beforeNegativeTable = next?.type === "table" && (next.props.indent ?? 0) < 0;
|
|
11468
|
+
const header = this.doc.headers.get(page.headerRel ?? "");
|
|
11469
|
+
const headerAnchors = header?.blocks.flatMap(
|
|
11470
|
+
(block) => block.type === "paragraph" ? this.collectAnchors(block) : []
|
|
11471
|
+
) ?? [];
|
|
11472
|
+
const beforeParagraphUnderUnwrappedHeader = next?.type === "paragraph" && page.headerGrown === true && headerAnchors.length > 0 && headerAnchors.every(
|
|
11473
|
+
(shape) => !("wrap" in shape) || shape.wrap === void 0 || shape.wrap === "none"
|
|
11474
|
+
);
|
|
11475
|
+
if (!beforeNegativeTable && !beforeParagraphUnderUnwrappedHeader) return;
|
|
11476
|
+
const firstBodyItem = page.items.findIndex(
|
|
11477
|
+
(item) => item.kind !== "text" || item.text.length > 0
|
|
11478
|
+
);
|
|
11479
|
+
if (firstBodyItem < 0) return;
|
|
11480
|
+
const paraProps = this.doc.effectiveParaProps(opening);
|
|
11481
|
+
const markProps = this.doc.effectiveRunProps(opening, paraProps.markRunProps ?? {});
|
|
11482
|
+
let overlap = this.measurer.metrics(
|
|
11483
|
+
fontOf(markProps, this.doc.styles.defaultRPr.font ?? "Calibri")
|
|
11484
|
+
).lineHeight;
|
|
11485
|
+
if (beforeParagraphUnderUnwrappedHeader) {
|
|
11486
|
+
overlap += paraProps.spacingAfter ?? 0;
|
|
11487
|
+
}
|
|
11488
|
+
for (let i = firstBodyItem; i < page.items.length; i++) {
|
|
11489
|
+
offsetItem(page.items[i], 0, -overlap);
|
|
11490
|
+
}
|
|
11491
|
+
page.openingFlowOverlapApplied = true;
|
|
11492
|
+
}
|
|
11366
11493
|
/** Whether this document is in the envelope the incremental path handles:
|
|
11367
11494
|
* one section, no notes, single column, upright flow, no line numbering /
|
|
11368
11495
|
* mirror margins / vertical alignment, and no positioned/floating content or
|
|
@@ -11621,7 +11748,7 @@ var Engine = class {
|
|
|
11621
11748
|
const contentWidth = shifted.sp.pageWidth - shifted.sp.marginLeft - shifted.sp.marginRight - shifted.sp.gutter;
|
|
11622
11749
|
const header = this.doc.headers.get(headerRel ?? "");
|
|
11623
11750
|
const footer = this.doc.footers.get(footerRel ?? "");
|
|
11624
|
-
const headerHeight = this.measureHeaderFooter(header, shifted, contentWidth, this.pageFieldFrameOverlay(header));
|
|
11751
|
+
const headerHeight = this.measureHeaderFooter(header, shifted, contentWidth, this.pageFieldFrameOverlay(header), true);
|
|
11625
11752
|
const footerHeight = this.measureHeaderFooter(footer, shifted, contentWidth, this.pageFieldFrameOverlay(footer));
|
|
11626
11753
|
if (headerHeight !== page.headerHeight || footerHeight !== page.footerHeight) return null;
|
|
11627
11754
|
shifted.headerHeight = headerHeight;
|
|
@@ -11999,8 +12126,8 @@ var Engine = class {
|
|
|
11999
12126
|
displayNumber,
|
|
12000
12127
|
headerHeight: 0,
|
|
12001
12128
|
footerHeight: 0,
|
|
12002
|
-
bodyTop:
|
|
12003
|
-
bandTop:
|
|
12129
|
+
bodyTop: sp.marginTop,
|
|
12130
|
+
bandTop: sp.marginTop,
|
|
12004
12131
|
softTop: !sectionStart,
|
|
12005
12132
|
bodyBottom: sp.pageHeight - Math.abs(sp.marginBottom),
|
|
12006
12133
|
colXs,
|
|
@@ -12024,13 +12151,17 @@ var Engine = class {
|
|
|
12024
12151
|
}
|
|
12025
12152
|
const header = this.doc.headers.get(page.headerRel ?? "");
|
|
12026
12153
|
const footer = this.doc.footers.get(page.footerRel ?? "");
|
|
12027
|
-
const headerH = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header));
|
|
12154
|
+
const headerH = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header), true);
|
|
12028
12155
|
const footerOverlay = this.pageFieldFrameOverlay(footer);
|
|
12029
12156
|
const footerH = this.measureHeaderFooter(footer, page, contentWidth, footerOverlay);
|
|
12030
12157
|
page.headerHeight = headerH;
|
|
12031
12158
|
page.footerHeight = footerH;
|
|
12032
12159
|
if (sp.marginTop >= 0) {
|
|
12033
|
-
|
|
12160
|
+
const headerBodyHeight = this.doc.compatibilityMode < 15 && header?.blocks.every((block) => block.type === "paragraph" && !paragraphHasContent(block)) ? ptToPx(7) : headerH;
|
|
12161
|
+
page.bodyTop = Math.max(
|
|
12162
|
+
sp.marginTop,
|
|
12163
|
+
headerBodyHeight > 0 ? sp.headerDistance + headerBodyHeight : 0
|
|
12164
|
+
);
|
|
12034
12165
|
page.bandTop = page.bodyTop;
|
|
12035
12166
|
page.headerGrown = page.bodyTop > sp.marginTop;
|
|
12036
12167
|
}
|
|
@@ -12270,7 +12401,7 @@ var Engine = class {
|
|
|
12270
12401
|
if (this.col + 1 < this.cur.colXs.length) {
|
|
12271
12402
|
this.col++;
|
|
12272
12403
|
this.y = this.columnStartY(this.col);
|
|
12273
|
-
this.bannerSlotUsed = 0;
|
|
12404
|
+
this.bannerSlotUsed = this.cur.bannerTop !== void 0 ? this.cur.openingColumnReserve ?? 0 : 0;
|
|
12274
12405
|
this.lastParaSpacingAfter = 0;
|
|
12275
12406
|
this.lastParaAfterPad = 0;
|
|
12276
12407
|
this.lastParaAfterPad = 0;
|
|
@@ -12607,7 +12738,7 @@ var Engine = class {
|
|
|
12607
12738
|
const runs = c.type === "run" ? [c] : c.runs;
|
|
12608
12739
|
for (const r of runs) {
|
|
12609
12740
|
for (const rc of r.content) {
|
|
12610
|
-
if (rc.kind !== "noteRef" || rc.self) continue;
|
|
12741
|
+
if (rc.kind !== "noteRef" || rc.self || rc.customMarkFollows) continue;
|
|
12611
12742
|
if (rc.noteType === "footnote" && this.doc.footnotes.has(rc.id) && !this.footnoteNumbers.has(rc.id)) {
|
|
12612
12743
|
this.footnoteNumbers.set(rc.id, fnStart + fn++);
|
|
12613
12744
|
} else if (rc.noteType === "endnote" && this.doc.endnotes.has(rc.id) && !this.endnoteNumbers.has(rc.id)) {
|
|
@@ -13120,6 +13251,20 @@ var Engine = class {
|
|
|
13120
13251
|
}
|
|
13121
13252
|
placeParagraph(para, prev, next, siblings, index) {
|
|
13122
13253
|
const props = this.doc.effectiveParaProps(para);
|
|
13254
|
+
const detachedFootnotes = customFootnoteAnchorIds(para);
|
|
13255
|
+
if (detachedFootnotes && next?.type === "paragraph") {
|
|
13256
|
+
const nextProps2 = this.doc.effectiveParaProps(next);
|
|
13257
|
+
const nextFrame = nextProps2.frame ? this.resolveFrame(nextProps2.frame) : void 0;
|
|
13258
|
+
if (nextFrame?.wrap === "notBeside" && nextFrame.w !== void 0 && this.cur.colXs.length > 1 && nextFrame.w > this.colWidth + 1) {
|
|
13259
|
+
for (const id of detachedFootnotes) this.registerFootnote(id, this.cur);
|
|
13260
|
+
const markProps = this.doc.effectiveRunProps(para, props.markRunProps ?? {});
|
|
13261
|
+
this.cur.openingColumnReserve = this.measurer.metrics(
|
|
13262
|
+
fontOf(markProps, this.doc.styles.defaultRPr.font ?? "Calibri")
|
|
13263
|
+
).lineHeight;
|
|
13264
|
+
this.customNoteBannerFit = true;
|
|
13265
|
+
return;
|
|
13266
|
+
}
|
|
13267
|
+
}
|
|
13123
13268
|
if (this.consumedFrames.has(para)) return;
|
|
13124
13269
|
if (props.frame && !props.dropCap && this.cur.physIndex !== -1) {
|
|
13125
13270
|
const fr = this.resolveFrame(props.frame);
|
|
@@ -13252,12 +13397,18 @@ var Engine = class {
|
|
|
13252
13397
|
if (breakBeforeForced && !(isLeadingPageBreak && keepSpBeforeAtPageTop)) dropSpaceBefore = true;
|
|
13253
13398
|
if (this.docGridDropBefore) {
|
|
13254
13399
|
if (props.snapToGrid === false && this.sp.docGridLinePitch) {
|
|
13255
|
-
const reduction = 2 * this.sp.docGridLinePitch;
|
|
13400
|
+
const reduction = (props.spacingBefore ?? 0) > 0 ? 4 * this.sp.docGridLinePitch : 2 * this.sp.docGridLinePitch;
|
|
13256
13401
|
this.cur.bodyTop -= reduction;
|
|
13257
13402
|
this.y -= reduction;
|
|
13403
|
+
} else if (para.props.styleId === "Heading1" && this.sp.docGridLinePitch) {
|
|
13404
|
+
const reduction = 3 * this.sp.docGridLinePitch - ptToPx(1.5);
|
|
13405
|
+
this.cur.bodyTop -= reduction;
|
|
13406
|
+
this.y -= reduction;
|
|
13407
|
+
dropSpaceBefore = true;
|
|
13408
|
+
} else {
|
|
13409
|
+
dropSpaceBefore = true;
|
|
13258
13410
|
}
|
|
13259
13411
|
this.docGridDropBefore = false;
|
|
13260
|
-
dropSpaceBefore = true;
|
|
13261
13412
|
}
|
|
13262
13413
|
const rawSpacingBefore = dropSpaceBefore ? 0 : props.spacingBefore ?? 0;
|
|
13263
13414
|
let paraTopEstimate = this.y + rawSpacingBefore;
|
|
@@ -13431,7 +13582,7 @@ var Engine = class {
|
|
|
13431
13582
|
const nextProps = nextPara ? this.doc.effectiveParaProps(nextPara) : void 0;
|
|
13432
13583
|
const nextLeadBreak = nextPara ? leadingBreakOf(nextPara) : void 0;
|
|
13433
13584
|
let legacyBreakChain = false;
|
|
13434
|
-
if (lines.length > 0 && this.pageIsEmptyAtCursor() && this.doc.compatibilityMode < 15 && this.sp.docGridType === "default" && props.keepNext && nextPara && nextProps?.keepNext && nextLeadBreak?.type === "page") {
|
|
13585
|
+
if (lines.length > 0 && this.pageIsEmptyAtCursor() && this.doc.compatibilityMode < 15 && this.sp.docGridType === "default" && !this.cur.footerRel && props.keepNext && nextPara && nextProps?.keepNext && nextLeadBreak?.type === "page") {
|
|
13435
13586
|
const breakProps = this.doc.effectiveRunProps(nextPara, nextLeadBreak.run.props);
|
|
13436
13587
|
const breakFont = fontOf(breakProps, this.doc.styles.defaultRPr.font ?? "Calibri");
|
|
13437
13588
|
let breakHeight = this.measurer.metrics(breakFont).lineHeight;
|
|
@@ -13602,6 +13753,7 @@ var Engine = class {
|
|
|
13602
13753
|
let simCol = this.col;
|
|
13603
13754
|
let simOnCurrentPage = true;
|
|
13604
13755
|
let simBannerUsed = this.bannerSlotUsed;
|
|
13756
|
+
const paragraphOverhang = this.customNoteBannerFit ? CUSTOM_NOTE_BANNER_OVERHANG : 0;
|
|
13605
13757
|
const updateBottom = () => {
|
|
13606
13758
|
bottom = simOnCurrentPage && this.balanceBottom !== void 0 && simCol + 1 < this.cur.colXs.length ? this.balanceBottom - simBannerUsed : this.cur.bodyBottom - (simOnCurrentPage ? this.footnoteReserve(this.cur, simCol) + simBannerUsed : 0);
|
|
13607
13759
|
};
|
|
@@ -13624,16 +13776,17 @@ var Engine = class {
|
|
|
13624
13776
|
}
|
|
13625
13777
|
};
|
|
13626
13778
|
const nextSimColumn = () => {
|
|
13627
|
-
simBannerUsed = 0;
|
|
13628
13779
|
simNotes = 0;
|
|
13629
13780
|
simNoted.clear();
|
|
13630
13781
|
if (simCol + 1 < this.cur.colXs.length) {
|
|
13631
13782
|
simCol++;
|
|
13632
13783
|
simY = simOnCurrentPage ? this.columnStartY(simCol) : this.cur.bodyTop;
|
|
13784
|
+
simBannerUsed = simOnCurrentPage && this.cur.bannerTop !== void 0 ? this.cur.openingColumnReserve ?? 0 : 0;
|
|
13633
13785
|
} else {
|
|
13634
13786
|
simCol = 0;
|
|
13635
13787
|
simOnCurrentPage = false;
|
|
13636
13788
|
simY = this.cur.bodyTop;
|
|
13789
|
+
simBannerUsed = 0;
|
|
13637
13790
|
}
|
|
13638
13791
|
updateBottom();
|
|
13639
13792
|
};
|
|
@@ -13652,7 +13805,7 @@ var Engine = class {
|
|
|
13652
13805
|
const noteAdd = lineNoteHeights(lines[li]);
|
|
13653
13806
|
const baseNotes = simOnCurrentPage ? this.cur.footnoteH[simCol] ?? 0 : 0;
|
|
13654
13807
|
const simSep = simNotes + noteAdd > 0 && baseNotes === 0 ? this.noteSeparatorReserve(this.cur) : 0;
|
|
13655
|
-
const overflowsHere = !postTablePageBreak && (simBalancing ? simY > bottom + 0.01 : simY + lines[li].fitHeight + (li === lines.length - 1 ? keepNextTail : 0) > bottom - simNotes - noteAdd - simSep + 0.01);
|
|
13808
|
+
const overflowsHere = !postTablePageBreak && (simBalancing ? simY > bottom + 0.01 : simY + lines[li].fitHeight + (li === lines.length - 1 ? keepNextTail : 0) > bottom - simNotes - noteAdd - simSep + paragraphOverhang + 0.01);
|
|
13656
13809
|
if (overflowsHere && li === segStart && segStart === 0 && onPartialPage && !simBalancing) {
|
|
13657
13810
|
breaks2.add(0);
|
|
13658
13811
|
segStart = 0;
|
|
@@ -13738,7 +13891,7 @@ var Engine = class {
|
|
|
13738
13891
|
const pendingNotes = this.pendingNoteHeight(line2);
|
|
13739
13892
|
const balancing = this.balanceBottom !== void 0 && this.col + 1 < this.cur.colXs.length;
|
|
13740
13893
|
const balBottomBased = balancing && this.colWidth < 40;
|
|
13741
|
-
const overflow = !postTablePageBreak && (balancing ? (balBottomBased ? this.y + line2.fitHeight : this.y) > this.bodyBottom + 0.01 : this.y + line2.fitHeight > this.bodyBottom - pendingNotes + 0.01) && !this.pageIsEmptyAtCursor();
|
|
13894
|
+
const overflow = !postTablePageBreak && (balancing ? (balBottomBased ? this.y + line2.fitHeight : this.y) > this.bodyBottom + 0.01 : this.y + line2.fitHeight > this.bodyBottom - pendingNotes + (this.customNoteBannerFit ? CUSTOM_NOTE_BANNER_OVERHANG : 0) + 0.01) && !this.pageIsEmptyAtCursor();
|
|
13742
13895
|
if ((planned || overflow) && li > fragStartLine) {
|
|
13743
13896
|
closeFragment(li, false);
|
|
13744
13897
|
this.nextColumn();
|
|
@@ -14406,13 +14559,35 @@ var Engine = class {
|
|
|
14406
14559
|
y = Math.max(y, pendingPageFrame.bottom);
|
|
14407
14560
|
pendingPageFrame = null;
|
|
14408
14561
|
}
|
|
14409
|
-
y = this.layoutTableInFrame(block, fake, 0, y, width, fields);
|
|
14562
|
+
y = this.layoutTableInFrame(block, fake, 0, y, width, fields, inCell === true);
|
|
14410
14563
|
framePrevAfter = 0;
|
|
14411
14564
|
}
|
|
14412
14565
|
}
|
|
14413
14566
|
if (pendingPageFrame) y = Math.max(y, pendingPageFrame.bottom);
|
|
14567
|
+
const itemBottom = (item) => {
|
|
14568
|
+
if (item.kind === "text") return (item.glyphTop ?? item.lineTop) + item.lineHeight;
|
|
14569
|
+
if (item.kind === "rect" || item.kind === "image" || item.kind === "path" || item.kind === "drawingHit") {
|
|
14570
|
+
return item.y + item.height;
|
|
14571
|
+
}
|
|
14572
|
+
if (item.kind === "edge") return Math.max(item.y1, item.y2);
|
|
14573
|
+
if (item.kind === "wordart" || item.kind === "warptext") return item.y + item.height;
|
|
14574
|
+
return 0;
|
|
14575
|
+
};
|
|
14576
|
+
const headerBandBottom = this.sp.marginTop - (origin?.y ?? 0);
|
|
14577
|
+
const paintedHeaderBottom = items.reduce((bottom, item) => {
|
|
14578
|
+
const itemEnd = itemBottom(item);
|
|
14579
|
+
return "behind" in item && item.behind && itemEnd <= headerBandBottom + 0.01 ? Math.max(bottom, itemEnd) : bottom;
|
|
14580
|
+
}, 0);
|
|
14581
|
+
const wrappedBottom = (this.floats.get(fake) ?? []).reduce(
|
|
14582
|
+
(bottom, float) => Math.max(bottom, float.y1 - (origin?.y ?? 0)),
|
|
14583
|
+
0
|
|
14584
|
+
);
|
|
14414
14585
|
this.floats.delete(fake);
|
|
14415
|
-
return {
|
|
14586
|
+
return {
|
|
14587
|
+
items,
|
|
14588
|
+
height: y + pageFramePhantomH,
|
|
14589
|
+
contentBottom: Math.max(y + pageFramePhantomH, paintedHeaderBottom, wrappedBottom)
|
|
14590
|
+
};
|
|
14416
14591
|
}
|
|
14417
14592
|
/**
|
|
14418
14593
|
* Emit floating shapes anchored at (textX, textY). Coordinates in the shape
|
|
@@ -14818,7 +14993,7 @@ var Engine = class {
|
|
|
14818
14993
|
page.items.push(it);
|
|
14819
14994
|
}
|
|
14820
14995
|
}
|
|
14821
|
-
measureHeaderFooter(hf, page, contentWidth, overlayPageFrame = false) {
|
|
14996
|
+
measureHeaderFooter(hf, page, contentWidth, overlayPageFrame = false, reserveBodyClearance = false) {
|
|
14822
14997
|
if (!hf || hf.blocks.length === 0) return 0;
|
|
14823
14998
|
const fields = {
|
|
14824
14999
|
pageNumber: () => page.displayNumber,
|
|
@@ -14827,10 +15002,25 @@ var Engine = class {
|
|
|
14827
15002
|
};
|
|
14828
15003
|
const snapshot = new Map(Array.from(this.counters, ([k, v]) => [k, [...v]]));
|
|
14829
15004
|
const seenSnapshot = new Set(this.seenNumIds);
|
|
14830
|
-
const {
|
|
15005
|
+
const origin = reserveBodyClearance ? { x: page.sp.marginLeft + page.sp.gutter, y: page.sp.headerDistance } : void 0;
|
|
15006
|
+
const { height, contentBottom } = this.layoutFrame(
|
|
15007
|
+
hf.blocks,
|
|
15008
|
+
contentWidth,
|
|
15009
|
+
fields,
|
|
15010
|
+
origin,
|
|
15011
|
+
false,
|
|
15012
|
+
overlayPageFrame
|
|
15013
|
+
);
|
|
14831
15014
|
this.counters = snapshot;
|
|
14832
15015
|
this.seenNumIds = seenSnapshot;
|
|
14833
|
-
|
|
15016
|
+
const anchors = hf.blocks.flatMap(
|
|
15017
|
+
(block) => block.type === "paragraph" ? this.collectAnchors(block) : []
|
|
15018
|
+
);
|
|
15019
|
+
const hasOnlyUnwrappedAnchors = anchors.length > 0 && anchors.every(
|
|
15020
|
+
(shape) => !("wrap" in shape) || shape.wrap === void 0 || shape.wrap === "none"
|
|
15021
|
+
);
|
|
15022
|
+
const complexHeader = anchors.length > 0 || hf.blocks.some((block) => block.type === "table");
|
|
15023
|
+
return reserveBodyClearance ? Math.max(height, contentBottom) + (!hasOnlyUnwrappedAnchors && complexHeader ? ptToPx(22.5) : 0) : height;
|
|
14834
15024
|
}
|
|
14835
15025
|
pageFieldFrameOverlay(hf) {
|
|
14836
15026
|
if (!hf) return false;
|
|
@@ -14892,7 +15082,10 @@ var Engine = class {
|
|
|
14892
15082
|
const measured = this.layoutFrame(footer.blocks, contentWidth, fields, void 0, false, overlayPageFrame);
|
|
14893
15083
|
this.counters = snapshot;
|
|
14894
15084
|
this.seenNumIds = seenSnapshot;
|
|
14895
|
-
const
|
|
15085
|
+
const legacyPageFrame = this.doc.compatibilityMode < 15 && footer.blocks.some(
|
|
15086
|
+
(block) => block.type === "paragraph" && this.doc.effectiveParaProps(block).frame?.vAnchor === "page"
|
|
15087
|
+
);
|
|
15088
|
+
const top = sp.pageHeight - sp.footerDistance - (legacyPageFrame ? 0 : measured.height);
|
|
14896
15089
|
snapshot = new Map(Array.from(this.counters, ([k, v]) => [k, [...v]]));
|
|
14897
15090
|
seenSnapshot = new Set(this.seenNumIds);
|
|
14898
15091
|
this.hfMarginVTop = page.bodyTop;
|
|
@@ -15271,7 +15464,14 @@ var Engine = class {
|
|
|
15271
15464
|
if (cell.props.margins?.top !== void 0) topPad = Math.max(topPad, cell.props.margins.top);
|
|
15272
15465
|
if (cell.props.margins?.bottom !== void 0) bottomPad = Math.max(bottomPad, cell.props.margins.bottom);
|
|
15273
15466
|
}
|
|
15274
|
-
if (row.props.heightRule === "exact")
|
|
15467
|
+
if (row.props.heightRule === "exact") {
|
|
15468
|
+
return this.doc.compatibilityMode < 15 ? trHeight : trHeight + topPad;
|
|
15469
|
+
}
|
|
15470
|
+
if (this.doc.compatibilityMode < 15) {
|
|
15471
|
+
const legacyBottomPad = bottomPad >= ptToPx(1) ? bottomPad : 0;
|
|
15472
|
+
const legacyTopPad = row.props.heightRule === "atLeast" && (row.props.height ?? 0) >= ptToPx(30) ? Math.max(topPad - ptToPx(0.25), 0) : topPad;
|
|
15473
|
+
return Math.max(contentHeight, trHeight + legacyTopPad + legacyBottomPad);
|
|
15474
|
+
}
|
|
15275
15475
|
const borderPad = this.rowBorderShare(tbl, ri);
|
|
15276
15476
|
return Math.max(contentHeight, trHeight + topPad + bottomPad + borderPad);
|
|
15277
15477
|
}
|
|
@@ -15491,7 +15691,7 @@ var Engine = class {
|
|
|
15491
15691
|
};
|
|
15492
15692
|
let guard = 0;
|
|
15493
15693
|
const noteReserve = this.rowNoteHeight(laid) + this.footnoteReserve(this.cur, this.col);
|
|
15494
|
-
const overhang = noteReserve > 0 || row.props.cantSplit
|
|
15694
|
+
const overhang = noteReserve > 0 || row.props.heightRule === "exact" ? 0 : row.props.cantSplit ? this.doc.compatibilityMode < 15 && (row.props.heightRule !== "atLeast" || (row.props.height ?? 0) >= ptToPx(2)) ? this.cur.footerHeight : 0 : ROW_OVERHANG_TOL;
|
|
15495
15695
|
while (this.y + rowHeight > this.bodyBottom - this.rowNoteHeight(laid) + overhang + 0.01 && guard++ < 50) {
|
|
15496
15696
|
const atColumnTop = this.pageIsEmptyAtCursor() || this.y <= this.cur.bodyTop + this.rowBorderWidths(tbl, ri).top / 2 + 0.01;
|
|
15497
15697
|
const cantSplitHolds = row.props.cantSplit === true && (rowHeight <= this.cur.bodyBottom - this.cur.bodyTop + 0.01 || !atColumnTop);
|
|
@@ -15710,9 +15910,9 @@ var Engine = class {
|
|
|
15710
15910
|
});
|
|
15711
15911
|
}
|
|
15712
15912
|
}
|
|
15713
|
-
layoutTableInFrame(tbl, fake, x0, y, width, fields) {
|
|
15913
|
+
layoutTableInFrame(tbl, fake, x0, y, width, fields, nested) {
|
|
15714
15914
|
this.ensureTableBorders(tbl);
|
|
15715
|
-
const widths = this.resolveGridWidths(tbl, width,
|
|
15915
|
+
const widths = this.resolveGridWidths(tbl, width, nested);
|
|
15716
15916
|
const saveY = this.y;
|
|
15717
15917
|
const saveCur = this.cur;
|
|
15718
15918
|
const saveCol = this.col;
|
|
@@ -15978,6 +16178,7 @@ var Engine = class {
|
|
|
15978
16178
|
}
|
|
15979
16179
|
let maxH = 0;
|
|
15980
16180
|
let measuredContentH = 0;
|
|
16181
|
+
const effectiveBottomPad = (bottom) => this.doc.compatibilityMode < 15 && row.props.heightRule === "atLeast" && (row.props.height ?? 0) < ptToPx(2) && (bottom ?? 0) >= ptToPx(2) ? (bottom ?? 0) / 2 : bottom ?? 0;
|
|
15981
16182
|
for (let ci = 0; ci < row.cells.length; ci++) {
|
|
15982
16183
|
const cell = row.cells[ci];
|
|
15983
16184
|
const { x, width: w, margins: m } = geometry[ci];
|
|
@@ -15997,7 +16198,7 @@ var Engine = class {
|
|
|
15997
16198
|
true
|
|
15998
16199
|
);
|
|
15999
16200
|
for (const it of items) offsetItem(it, m.left ?? 0, m.top ?? 0);
|
|
16000
|
-
const cellHeight = height + (m.top ?? 0) + (m.bottom
|
|
16201
|
+
const cellHeight = height + (m.top ?? 0) + effectiveBottomPad(m.bottom);
|
|
16001
16202
|
cells[ci] = { items, height: cellHeight, x, width: w, cellIdx: ci };
|
|
16002
16203
|
measuredContentH = Math.max(measuredContentH, height);
|
|
16003
16204
|
maxH = Math.max(maxH, cellHeight);
|
|
@@ -16041,7 +16242,7 @@ var Engine = class {
|
|
|
16041
16242
|
it.rotate = { deg, ox: centerX - it.x, oy: centerY - top };
|
|
16042
16243
|
}
|
|
16043
16244
|
}
|
|
16044
|
-
const cellHeight = frameWidth + (m.top ?? 0) + (m.bottom
|
|
16245
|
+
const cellHeight = frameWidth + (m.top ?? 0) + effectiveBottomPad(m.bottom);
|
|
16045
16246
|
cells[ci] = { items, height: cellHeight, x, width: w, cellIdx: ci, rotated: true };
|
|
16046
16247
|
maxH = Math.max(maxH, cellHeight);
|
|
16047
16248
|
}
|
|
@@ -16190,6 +16391,24 @@ var Engine = class {
|
|
|
16190
16391
|
}
|
|
16191
16392
|
}
|
|
16192
16393
|
};
|
|
16394
|
+
function customFootnoteAnchorIds(p) {
|
|
16395
|
+
const ids = [];
|
|
16396
|
+
for (const child4 of p.children) {
|
|
16397
|
+
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
16398
|
+
for (const run of runs) {
|
|
16399
|
+
for (const content of run.content) {
|
|
16400
|
+
if (content.kind === "text") {
|
|
16401
|
+
if (content.text.trim().length > 0) return void 0;
|
|
16402
|
+
} else if (content.kind === "noteRef" && content.noteType === "footnote" && !content.self && content.customMarkFollows) {
|
|
16403
|
+
ids.push(content.id);
|
|
16404
|
+
} else {
|
|
16405
|
+
return void 0;
|
|
16406
|
+
}
|
|
16407
|
+
}
|
|
16408
|
+
}
|
|
16409
|
+
}
|
|
16410
|
+
return ids.length > 0 ? ids : void 0;
|
|
16411
|
+
}
|
|
16193
16412
|
function isEmptyParagraph(p) {
|
|
16194
16413
|
for (const child4 of p.children) {
|
|
16195
16414
|
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
@@ -17957,6 +18176,11 @@ function renderItem(doc, item, urls) {
|
|
|
17957
18176
|
hit.dataset.dxwDrawing = "1";
|
|
17958
18177
|
if (item.ink) hit.dataset.dxwInk = "1";
|
|
17959
18178
|
if (item.smartArt) hit.dataset.dxwSmartArt = "1";
|
|
18179
|
+
if (item.height < 12) {
|
|
18180
|
+
const target = document.createElement("div");
|
|
18181
|
+
target.style.cssText = `position:absolute;left:0;top:${-(12 - item.height) / 2}px;width:100%;height:12px;cursor:move;`;
|
|
18182
|
+
hit.appendChild(target);
|
|
18183
|
+
}
|
|
17960
18184
|
return hit;
|
|
17961
18185
|
}
|
|
17962
18186
|
case "edge": {
|
|
@@ -18416,6 +18640,10 @@ function renderText(item) {
|
|
|
18416
18640
|
el16.style.alignItems = "flex-end";
|
|
18417
18641
|
el16.style.whiteSpace = "pre";
|
|
18418
18642
|
el16.style.font = cssFont(item.font);
|
|
18643
|
+
if (item.font.paintDY) {
|
|
18644
|
+
const transform = el16.style.transform;
|
|
18645
|
+
el16.style.transform = `${transform ? `${transform} ` : ""}translateY(${item.font.paintDY}px)`;
|
|
18646
|
+
}
|
|
18419
18647
|
}
|
|
18420
18648
|
if (item.rtl) {
|
|
18421
18649
|
el16.style.direction = "rtl";
|
|
@@ -18479,7 +18707,8 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18479
18707
|
}
|
|
18480
18708
|
const horizontal = Math.abs(y2 - y1) < 0.01;
|
|
18481
18709
|
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
18482
|
-
const
|
|
18710
|
+
const declaredWidth = border.rawWidth !== void 0 && border.rawWidth < 0.25 ? border.rawWidth : border.width;
|
|
18711
|
+
const w = Math.max(1 / dpr, Math.round(declaredWidth * dpr) / dpr);
|
|
18483
18712
|
const snap = (v) => Math.round(v * dpr) / dpr;
|
|
18484
18713
|
const place = border.space === 0 ? snap : (v) => v;
|
|
18485
18714
|
const dashPattern = border.style === "dashed" || border.style === "dotDash" || border.style === "dotDotDash" ? [3, 1] : border.style === "dotted" ? [1, 1] : null;
|
|
@@ -20700,23 +20929,44 @@ function insertShapeAt(doc, caretT, preset, text = "") {
|
|
|
20700
20929
|
if (!caretRun || !parent || localName(caretRun.name) !== "r") return null;
|
|
20701
20930
|
const w = prefixOf8(caretRun);
|
|
20702
20931
|
const id = String(doc.nextDrawingId());
|
|
20703
|
-
const
|
|
20704
|
-
const
|
|
20932
|
+
const isLine = preset === "line";
|
|
20933
|
+
const width = isLine ? 240 : preset === "textBox" ? 240 : 192;
|
|
20934
|
+
const height = isLine ? 2 : preset === "textBox" ? 72 : 96;
|
|
20705
20935
|
const cx = String(Math.round(width * EMU_PER_PX4));
|
|
20706
20936
|
const cy = String(Math.round(height * EMU_PER_PX4));
|
|
20707
20937
|
const geometry = preset === "roundedRectangle" ? "roundRect" : preset === "rectangle" || preset === "textBox" ? "rect" : preset;
|
|
20708
20938
|
const isTextBox = preset === "textBox";
|
|
20709
|
-
const shapeName = isTextBox ? `Text Box ${id}` : `Shape ${id}`;
|
|
20939
|
+
const shapeName = isLine ? `Line ${id}` : isTextBox ? `Text Box ${id}` : `Shape ${id}`;
|
|
20710
20940
|
const spPr = [
|
|
20711
|
-
el6("a:xfrm", {}, [
|
|
20941
|
+
el6("a:xfrm", {}, [
|
|
20942
|
+
el6("a:off", { x: "0", y: "0" }),
|
|
20943
|
+
el6("a:ext", { cx, cy })
|
|
20944
|
+
]),
|
|
20712
20945
|
el6("a:prstGeom", { prst: geometry }, [el6("a:avLst")]),
|
|
20713
|
-
isTextBox ? el6("a:noFill") : el6("a:solidFill", {}, [el6("a:srgbClr", { val: "4472C4" })]),
|
|
20714
|
-
el6("a:ln", { w: "12700" }, [el6("a:solidFill", {}, [el6("a:srgbClr", { val: isTextBox ? "404040" : "2F5597" })])])
|
|
20946
|
+
isTextBox || isLine ? el6("a:noFill") : el6("a:solidFill", {}, [el6("a:srgbClr", { val: "4472C4" })]),
|
|
20947
|
+
el6("a:ln", { w: "12700" }, [el6("a:solidFill", {}, [el6("a:srgbClr", { val: isTextBox || isLine ? "404040" : "2F5597" })])])
|
|
20715
20948
|
];
|
|
20716
20949
|
const textRun = el6(`${w}r`, {}, [
|
|
20717
20950
|
el6(`${w}rPr`, {}, [el6(`${w}color`, { [`${w}val`]: isTextBox ? "202124" : "FFFFFF" }), el6(`${w}sz`, { [`${w}val`]: "22" })]),
|
|
20718
20951
|
el6(`${w}t`, { "xml:space": "preserve" }, [], text)
|
|
20719
20952
|
]);
|
|
20953
|
+
const shapeChildren = isLine ? [
|
|
20954
|
+
el6("wps:cNvCnPr", {}, [el6("a:cxnSpLocks", { noChangeShapeType: "1" })]),
|
|
20955
|
+
el6("wps:spPr", { bwMode: "auto" }, spPr),
|
|
20956
|
+
el6("wps:bodyPr")
|
|
20957
|
+
] : [
|
|
20958
|
+
el6("wps:cNvSpPr", isTextBox ? { txBox: "1" } : {}),
|
|
20959
|
+
el6("wps:spPr", {}, spPr),
|
|
20960
|
+
el6("wps:txbx", {}, [
|
|
20961
|
+
el6(`${w}txbxContent`, {}, [
|
|
20962
|
+
el6(`${w}p`, {}, [
|
|
20963
|
+
el6(`${w}pPr`, {}, [el6(`${w}jc`, { [`${w}val`]: isTextBox ? "left" : "center" })]),
|
|
20964
|
+
textRun
|
|
20965
|
+
])
|
|
20966
|
+
])
|
|
20967
|
+
]),
|
|
20968
|
+
el6("wps:bodyPr", { rot: "0", anchor: isTextBox ? "t" : "ctr" }, [el6("a:noAutofit")])
|
|
20969
|
+
];
|
|
20720
20970
|
const drawing = el6(`${w}drawing`, {}, [
|
|
20721
20971
|
el6("wp:anchor", {
|
|
20722
20972
|
"xmlns:wp": NS_WP3,
|
|
@@ -20736,24 +20986,12 @@ function insertShapeAt(doc, caretT, preset, text = "") {
|
|
|
20736
20986
|
el6("wp:positionV", { relativeFrom: "paragraph" }, [el6("wp:posOffset", {}, [], "0")]),
|
|
20737
20987
|
el6("wp:extent", { cx, cy }),
|
|
20738
20988
|
el6("wp:effectExtent", { l: "0", t: "0", r: "0", b: "0" }),
|
|
20739
|
-
el6("wp:wrapSquare", { wrapText: "bothSides" }),
|
|
20989
|
+
isLine ? el6("wp:wrapNone") : el6("wp:wrapSquare", { wrapText: "bothSides" }),
|
|
20740
20990
|
el6("wp:docPr", { id, name: shapeName }),
|
|
20741
20991
|
el6("wp:cNvGraphicFramePr"),
|
|
20742
20992
|
el6("a:graphic", { "xmlns:a": NS_A3 }, [
|
|
20743
20993
|
el6("a:graphicData", { uri: NS_WPS }, [
|
|
20744
|
-
el6("wps:wsp", { "xmlns:wps": NS_WPS },
|
|
20745
|
-
el6("wps:cNvSpPr", { txBox: "1" }),
|
|
20746
|
-
el6("wps:spPr", {}, spPr),
|
|
20747
|
-
el6("wps:txbx", {}, [
|
|
20748
|
-
el6(`${w}txbxContent`, {}, [
|
|
20749
|
-
el6(`${w}p`, {}, [
|
|
20750
|
-
el6(`${w}pPr`, {}, [el6(`${w}jc`, { [`${w}val`]: isTextBox ? "left" : "center" })]),
|
|
20751
|
-
textRun
|
|
20752
|
-
])
|
|
20753
|
-
])
|
|
20754
|
-
]),
|
|
20755
|
-
el6("wps:bodyPr", { rot: "0", anchor: isTextBox ? "t" : "ctr" }, [el6("a:noAutofit")])
|
|
20756
|
-
])
|
|
20994
|
+
el6("wps:wsp", { "xmlns:wps": NS_WPS }, shapeChildren)
|
|
20757
20995
|
])
|
|
20758
20996
|
])
|
|
20759
20997
|
])
|
|
@@ -20815,6 +21053,25 @@ function setDrawingWordArtText(doc, drawing, text) {
|
|
|
20815
21053
|
doc.refresh();
|
|
20816
21054
|
return true;
|
|
20817
21055
|
}
|
|
21056
|
+
function drawingLineStyle(drawing) {
|
|
21057
|
+
const line2 = descendant3(drawing, "ln");
|
|
21058
|
+
if (!line2) return null;
|
|
21059
|
+
const color = descendant3(line2, "srgbClr")?.attrs.val ?? "000000";
|
|
21060
|
+
const width = Math.max((parseInt(line2.attrs.w ?? "0", 10) || 0) / EMU_PER_PX4, 0.75);
|
|
21061
|
+
return { color: `#${color.toUpperCase()}`, width };
|
|
21062
|
+
}
|
|
21063
|
+
function setDrawingLineStyle(doc, drawing, color, widthPx) {
|
|
21064
|
+
const line2 = descendant3(drawing, "ln");
|
|
21065
|
+
if (!line2) return false;
|
|
21066
|
+
line2.attrs.w = String(Math.max(1, Math.round(widthPx * EMU_PER_PX4)));
|
|
21067
|
+
line2.children = line2.children.filter((child4) => {
|
|
21068
|
+
const name = localName(child4.name);
|
|
21069
|
+
return name !== "solidFill" && name !== "noFill";
|
|
21070
|
+
});
|
|
21071
|
+
line2.children.unshift(el6("a:solidFill", {}, [el6("a:srgbClr", { val: color.replace(/^#/, "").toUpperCase() })]));
|
|
21072
|
+
doc.refresh();
|
|
21073
|
+
return true;
|
|
21074
|
+
}
|
|
20818
21075
|
function insertInkAt(doc, caretT, points, color = "#202124", widthPx = 2, opacity = 1, refreshModel = true) {
|
|
20819
21076
|
if (points.length < 2) return null;
|
|
20820
21077
|
const caretRun = doc.findParentOf(caretT);
|
|
@@ -21223,6 +21480,111 @@ function deleteWatermark(doc, shapeEl) {
|
|
|
21223
21480
|
return true;
|
|
21224
21481
|
}
|
|
21225
21482
|
|
|
21483
|
+
// ../core/src/edit/dialog.ts
|
|
21484
|
+
var dialogSequence = 0;
|
|
21485
|
+
function requestTextInputDialog(anchor, options) {
|
|
21486
|
+
const doc = anchor.ownerDocument;
|
|
21487
|
+
const win = doc.defaultView;
|
|
21488
|
+
return new Promise((resolve) => {
|
|
21489
|
+
const id = `dxw-input-dialog-${++dialogSequence}`;
|
|
21490
|
+
const previousFocus = doc.activeElement instanceof HTMLElement ? doc.activeElement : null;
|
|
21491
|
+
const backdrop = doc.createElement("div");
|
|
21492
|
+
backdrop.className = "dxw-input-dialog-backdrop";
|
|
21493
|
+
backdrop.dataset.dxwInputDialog = "";
|
|
21494
|
+
backdrop.style.cssText = "position:fixed;inset:0;z-index:var(--dxw-dialog-z-index,1000);display:grid;place-items:center;padding:16px;box-sizing:border-box;background:var(--dxw-dialog-backdrop,rgba(32,33,36,.38));";
|
|
21495
|
+
if (win) {
|
|
21496
|
+
const computed = win.getComputedStyle(anchor);
|
|
21497
|
+
for (const property of [
|
|
21498
|
+
"--dxw-toolbar-fg",
|
|
21499
|
+
"--dxw-toolbar-border",
|
|
21500
|
+
"--dxw-toolbar-muted",
|
|
21501
|
+
"--dxw-accent",
|
|
21502
|
+
"--dxw-accent-fg",
|
|
21503
|
+
"--dxw-popover-bg",
|
|
21504
|
+
"--dxw-popover-shadow",
|
|
21505
|
+
"--dxw-dialog-backdrop",
|
|
21506
|
+
"--dxw-dialog-z-index",
|
|
21507
|
+
"--dxw-dialog-width",
|
|
21508
|
+
"--dxw-dialog-radius",
|
|
21509
|
+
"--dxw-dialog-field-bg"
|
|
21510
|
+
]) {
|
|
21511
|
+
const value = computed.getPropertyValue(property);
|
|
21512
|
+
if (value) backdrop.style.setProperty(property, value);
|
|
21513
|
+
}
|
|
21514
|
+
}
|
|
21515
|
+
const form = doc.createElement("form");
|
|
21516
|
+
form.className = "dxw-input-dialog";
|
|
21517
|
+
form.setAttribute("role", "dialog");
|
|
21518
|
+
form.setAttribute("aria-modal", "true");
|
|
21519
|
+
form.setAttribute("aria-labelledby", id);
|
|
21520
|
+
form.style.cssText = "width:min(var(--dxw-dialog-width,420px),calc(100vw - 32px));box-sizing:border-box;display:grid;gap:10px;padding:16px;border:1px solid var(--dxw-toolbar-border,#dadce0);border-radius:var(--dxw-dialog-radius,10px);color:var(--dxw-toolbar-fg,#3c4043);background:var(--dxw-popover-bg,#fff);box-shadow:var(--dxw-popover-shadow,0 8px 28px rgba(0,0,0,.24));font:13px system-ui,sans-serif;";
|
|
21521
|
+
const title = doc.createElement("strong");
|
|
21522
|
+
title.id = id;
|
|
21523
|
+
title.className = "dxw-input-dialog-title";
|
|
21524
|
+
title.textContent = options.title;
|
|
21525
|
+
title.style.cssText = "font-size:15px;line-height:1.35;";
|
|
21526
|
+
form.appendChild(title);
|
|
21527
|
+
const label = doc.createElement("label");
|
|
21528
|
+
label.className = "dxw-input-dialog-label";
|
|
21529
|
+
label.textContent = options.label ?? options.title;
|
|
21530
|
+
label.style.cssText = "display:grid;gap:5px;color:var(--dxw-toolbar-muted,#5f6368);font-size:12px;";
|
|
21531
|
+
const field = options.multiline ? doc.createElement("textarea") : doc.createElement("input");
|
|
21532
|
+
field.className = "dxw-input-dialog-field";
|
|
21533
|
+
field.value = options.value ?? "";
|
|
21534
|
+
field.placeholder = options.placeholder ?? "";
|
|
21535
|
+
field.setAttribute("aria-label", options.label ?? options.title);
|
|
21536
|
+
if (field instanceof HTMLTextAreaElement) field.rows = 4;
|
|
21537
|
+
field.style.cssText = "width:100%;min-height:34px;box-sizing:border-box;padding:7px 9px;border:1px solid var(--dxw-toolbar-border,#dadce0);border-radius:6px;outline:none;color:var(--dxw-toolbar-fg,#3c4043);background:var(--dxw-dialog-field-bg,var(--dxw-popover-bg,#fff));font:13px system-ui,sans-serif;resize:vertical;";
|
|
21538
|
+
label.appendChild(field);
|
|
21539
|
+
form.appendChild(label);
|
|
21540
|
+
const actions = doc.createElement("div");
|
|
21541
|
+
actions.className = "dxw-input-dialog-actions";
|
|
21542
|
+
actions.style.cssText = "display:flex;justify-content:flex-end;gap:7px;";
|
|
21543
|
+
const cancel = doc.createElement("button");
|
|
21544
|
+
cancel.type = "button";
|
|
21545
|
+
cancel.className = "dxw-input-dialog-cancel";
|
|
21546
|
+
cancel.textContent = "Cancel";
|
|
21547
|
+
cancel.style.cssText = "min-height:32px;padding:0 12px;border:1px solid var(--dxw-toolbar-border,#dadce0);border-radius:7px;color:var(--dxw-toolbar-fg,#3c4043);background:var(--dxw-popover-bg,#fff);cursor:pointer;font:600 12px system-ui,sans-serif;";
|
|
21548
|
+
const submit = doc.createElement("button");
|
|
21549
|
+
submit.type = "submit";
|
|
21550
|
+
submit.className = "dxw-input-dialog-submit";
|
|
21551
|
+
submit.textContent = options.submitLabel ?? "Apply";
|
|
21552
|
+
submit.style.cssText = "min-height:32px;padding:0 14px;border:1px solid transparent;border-radius:7px;color:var(--dxw-accent-fg,#fff);background:var(--dxw-accent,#1a73e8);cursor:pointer;font:600 12px system-ui,sans-serif;";
|
|
21553
|
+
actions.append(cancel, submit);
|
|
21554
|
+
form.appendChild(actions);
|
|
21555
|
+
backdrop.appendChild(form);
|
|
21556
|
+
doc.body.appendChild(backdrop);
|
|
21557
|
+
let finished = false;
|
|
21558
|
+
const finish = (value) => {
|
|
21559
|
+
if (finished) return;
|
|
21560
|
+
finished = true;
|
|
21561
|
+
doc.removeEventListener("keydown", onKeyDown, true);
|
|
21562
|
+
backdrop.remove();
|
|
21563
|
+
previousFocus?.focus({ preventScroll: true });
|
|
21564
|
+
resolve(value);
|
|
21565
|
+
};
|
|
21566
|
+
const onKeyDown = (event) => {
|
|
21567
|
+
if (event.key === "Escape") {
|
|
21568
|
+
event.preventDefault();
|
|
21569
|
+
finish(null);
|
|
21570
|
+
}
|
|
21571
|
+
};
|
|
21572
|
+
doc.addEventListener("keydown", onKeyDown, true);
|
|
21573
|
+
backdrop.addEventListener("mousedown", (event) => {
|
|
21574
|
+
if (event.target === backdrop) finish(null);
|
|
21575
|
+
});
|
|
21576
|
+
cancel.addEventListener("click", () => finish(null));
|
|
21577
|
+
form.addEventListener("submit", (event) => {
|
|
21578
|
+
event.preventDefault();
|
|
21579
|
+
finish(field.value);
|
|
21580
|
+
});
|
|
21581
|
+
requestAnimationFrame(() => {
|
|
21582
|
+
field.focus({ preventScroll: true });
|
|
21583
|
+
field.select();
|
|
21584
|
+
});
|
|
21585
|
+
});
|
|
21586
|
+
}
|
|
21587
|
+
|
|
21226
21588
|
// ../core/src/edit/grapheme.ts
|
|
21227
21589
|
var segmenter = null;
|
|
21228
21590
|
var segmenterTried = false;
|
|
@@ -21936,6 +22298,7 @@ var _DocxEditor = class _DocxEditor {
|
|
|
21936
22298
|
* snapshot that the following text insertion belongs to. */
|
|
21937
22299
|
this.pendingClickTypeCheckpoint = false;
|
|
21938
22300
|
this.clickTypeCheckpointUntil = 0;
|
|
22301
|
+
this.textContextMenu = null;
|
|
21939
22302
|
/** True while a drag-selection is in progress (checked by onMouseUp, which
|
|
21940
22303
|
* bubbles from the container BEFORE the document-level drag-end listener). */
|
|
21941
22304
|
this.dragSelecting = false;
|
|
@@ -22325,6 +22688,102 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22325
22688
|
};
|
|
22326
22689
|
/** Which part tree the element lives in: document body or header/footer. */
|
|
22327
22690
|
this.mathEditorEl = null;
|
|
22691
|
+
this.dismissTextContextMenu = () => {
|
|
22692
|
+
this.textContextMenu?.remove();
|
|
22693
|
+
this.textContextMenu = null;
|
|
22694
|
+
document.removeEventListener("mousedown", this.onContextMenuDocumentMouseDown);
|
|
22695
|
+
};
|
|
22696
|
+
this.onContextMenuDocumentMouseDown = (event) => {
|
|
22697
|
+
if (!this.textContextMenu?.contains(event.target)) this.dismissTextContextMenu();
|
|
22698
|
+
};
|
|
22699
|
+
this.onContextMenu = (event) => {
|
|
22700
|
+
const target = event.target;
|
|
22701
|
+
if (!target?.closest('[data-dxw-item-kind="text"]')) return;
|
|
22702
|
+
const caret = this.caretFromPoint(event.clientX, event.clientY);
|
|
22703
|
+
if (!caret || this.regionOf(caret.t) === "hf" !== this.inHeaderFooter) return;
|
|
22704
|
+
event.preventDefault();
|
|
22705
|
+
event.stopPropagation();
|
|
22706
|
+
this.dismissTextContextMenu();
|
|
22707
|
+
if (!this.hasSelection()) {
|
|
22708
|
+
this.caret = caret;
|
|
22709
|
+
this.selectWordAt(caret);
|
|
22710
|
+
}
|
|
22711
|
+
const menu = document.createElement("div");
|
|
22712
|
+
menu.dataset.dxwTextContextMenu = "1";
|
|
22713
|
+
menu.setAttribute("role", "menu");
|
|
22714
|
+
menu.style.cssText = `position:fixed;left:${event.clientX}px;top:${event.clientY}px;z-index:2147483647;min-width:210px;padding:5px;background:#fff;border:1px solid #dadce0;border-radius:8px;box-shadow:0 4px 18px rgba(0,0,0,.2);font:13px system-ui,sans-serif;color:#202124;`;
|
|
22715
|
+
const isApplePlatform = /Mac|iPhone|iPad/.test(navigator.platform);
|
|
22716
|
+
const mod = isApplePlatform ? "\u2318" : "Ctrl+";
|
|
22717
|
+
const item = (label, shortcut, disabled, action) => {
|
|
22718
|
+
const button = document.createElement("button");
|
|
22719
|
+
button.type = "button";
|
|
22720
|
+
button.disabled = disabled;
|
|
22721
|
+
button.setAttribute("role", "menuitem");
|
|
22722
|
+
button.style.cssText = `display:flex;width:100%;align-items:center;justify-content:space-between;gap:24px;border:0;border-radius:5px;padding:7px 9px;background:transparent;color:${disabled ? "#9aa0a6" : "#202124"};cursor:${disabled ? "default" : "pointer"};`;
|
|
22723
|
+
const name = document.createElement("span");
|
|
22724
|
+
name.textContent = label;
|
|
22725
|
+
const keys = document.createElement("span");
|
|
22726
|
+
keys.textContent = shortcut;
|
|
22727
|
+
keys.style.color = "#5f6368";
|
|
22728
|
+
keys.style.fontSize = "11px";
|
|
22729
|
+
button.append(name, keys);
|
|
22730
|
+
button.addEventListener("mouseenter", () => {
|
|
22731
|
+
if (!button.disabled) button.style.background = "#f1f3f4";
|
|
22732
|
+
});
|
|
22733
|
+
button.addEventListener("mouseleave", () => {
|
|
22734
|
+
button.style.background = "transparent";
|
|
22735
|
+
});
|
|
22736
|
+
button.addEventListener("click", () => {
|
|
22737
|
+
if (button.disabled) return;
|
|
22738
|
+
this.dismissTextContextMenu();
|
|
22739
|
+
action();
|
|
22740
|
+
});
|
|
22741
|
+
menu.appendChild(button);
|
|
22742
|
+
};
|
|
22743
|
+
const separator = () => {
|
|
22744
|
+
const line2 = document.createElement("div");
|
|
22745
|
+
line2.style.cssText = "height:1px;background:#e8eaed;margin:4px 2px;";
|
|
22746
|
+
menu.appendChild(line2);
|
|
22747
|
+
};
|
|
22748
|
+
const selectedText = selectionTextLogical(this.host.doc, this.getSelectionSegments());
|
|
22749
|
+
const clipboard = navigator.clipboard;
|
|
22750
|
+
const copy = () => clipboard.writeText(selectedText);
|
|
22751
|
+
item("Copy", `${mod}C`, !selectedText || !clipboard?.writeText, () => void copy());
|
|
22752
|
+
item("Cut", `${mod}X`, !selectedText || !clipboard?.writeText, () => {
|
|
22753
|
+
void copy().then(() => {
|
|
22754
|
+
this.host.history?.checkpoint();
|
|
22755
|
+
this.removeSelectedText();
|
|
22756
|
+
this.commit();
|
|
22757
|
+
});
|
|
22758
|
+
});
|
|
22759
|
+
item("Paste", `${mod}V`, !clipboard?.readText, () => {
|
|
22760
|
+
void clipboard.readText().then((text) => {
|
|
22761
|
+
if (text) this.insertText(text);
|
|
22762
|
+
});
|
|
22763
|
+
});
|
|
22764
|
+
separator();
|
|
22765
|
+
item("Bold", `${mod}B`, !selectedText, () => this.host.onFormatShortcut?.("bold"));
|
|
22766
|
+
item("Italic", `${mod}I`, !selectedText, () => this.host.onFormatShortcut?.("italic"));
|
|
22767
|
+
item("Underline", `${mod}U`, !selectedText, () => this.host.onFormatShortcut?.("underline"));
|
|
22768
|
+
separator();
|
|
22769
|
+
item("Link\u2026", `${mod}K`, !selectedText, () => this.host.onTextCommand?.("link"));
|
|
22770
|
+
item("New comment\u2026", isApplePlatform ? "\u2318\u2325A" : "Ctrl+Alt+M", !selectedText, () => this.host.onTextCommand?.("comment"));
|
|
22771
|
+
item("Bulleted list", `${mod}Shift+L`, false, () => this.host.onTextCommand?.("bullet"));
|
|
22772
|
+
item("Numbered list", `${mod}Shift+7`, false, () => this.host.onTextCommand?.("number"));
|
|
22773
|
+
separator();
|
|
22774
|
+
item("Align left", `${mod}L`, false, () => this.host.onTextCommand?.("alignLeft"));
|
|
22775
|
+
item("Center", `${mod}E`, false, () => this.host.onTextCommand?.("alignCenter"));
|
|
22776
|
+
item("Align right", `${mod}R`, false, () => this.host.onTextCommand?.("alignRight"));
|
|
22777
|
+
item("Justify", `${mod}J`, false, () => this.host.onTextCommand?.("justify"));
|
|
22778
|
+
separator();
|
|
22779
|
+
item("Select all", `${mod}A`, false, () => this.selectAll());
|
|
22780
|
+
document.body.appendChild(menu);
|
|
22781
|
+
const rect = menu.getBoundingClientRect();
|
|
22782
|
+
menu.style.left = `${Math.max(6, Math.min(event.clientX, window.innerWidth - rect.width - 6))}px`;
|
|
22783
|
+
menu.style.top = `${Math.max(6, Math.min(event.clientY, window.innerHeight - rect.height - 6))}px`;
|
|
22784
|
+
this.textContextMenu = menu;
|
|
22785
|
+
setTimeout(() => document.addEventListener("mousedown", this.onContextMenuDocumentMouseDown), 0);
|
|
22786
|
+
};
|
|
22328
22787
|
// ---------- keyboard ----------
|
|
22329
22788
|
this.onKeyDown = (e) => {
|
|
22330
22789
|
if (this.composing || e.isComposing || e.keyCode === 229) return;
|
|
@@ -22332,6 +22791,11 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22332
22791
|
this.pendingClickTypeCheckpoint = false;
|
|
22333
22792
|
this.clickTypeCheckpointUntil = 0;
|
|
22334
22793
|
}
|
|
22794
|
+
if (this.textContextMenu) {
|
|
22795
|
+
if (e.key === "Escape") e.preventDefault();
|
|
22796
|
+
this.dismissTextContextMenu();
|
|
22797
|
+
if (e.key === "Escape") return;
|
|
22798
|
+
}
|
|
22335
22799
|
if (e.key === "Escape" && this.drawingTool) {
|
|
22336
22800
|
e.preventDefault();
|
|
22337
22801
|
this.setDrawingTool(null);
|
|
@@ -22446,6 +22910,12 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22446
22910
|
}
|
|
22447
22911
|
}
|
|
22448
22912
|
const meta = e.metaKey || e.ctrlKey;
|
|
22913
|
+
const isApplePlatform = /Mac|iPhone|iPad/.test(navigator.platform);
|
|
22914
|
+
if (isApplePlatform ? e.metaKey && e.altKey && e.key.toLowerCase() === "a" : e.ctrlKey && e.altKey && e.key.toLowerCase() === "m") {
|
|
22915
|
+
e.preventDefault();
|
|
22916
|
+
if (this.hasSelection()) this.host.onTextCommand?.("comment");
|
|
22917
|
+
return;
|
|
22918
|
+
}
|
|
22449
22919
|
if (meta && e.altKey && /^[0-6]$/.test(e.key)) {
|
|
22450
22920
|
e.preventDefault();
|
|
22451
22921
|
this.host.onStyleShortcut?.(e.key === "0" ? null : `Heading${e.key}`);
|
|
@@ -22465,6 +22935,28 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22465
22935
|
}
|
|
22466
22936
|
return;
|
|
22467
22937
|
}
|
|
22938
|
+
if (!e.shiftKey && k === "k") {
|
|
22939
|
+
e.preventDefault();
|
|
22940
|
+
if (this.hasSelection()) this.host.onTextCommand?.("link");
|
|
22941
|
+
return;
|
|
22942
|
+
}
|
|
22943
|
+
if (e.shiftKey && (k === "l" || k === "8")) {
|
|
22944
|
+
e.preventDefault();
|
|
22945
|
+
this.host.onTextCommand?.("bullet");
|
|
22946
|
+
return;
|
|
22947
|
+
}
|
|
22948
|
+
if (e.shiftKey && k === "7") {
|
|
22949
|
+
e.preventDefault();
|
|
22950
|
+
this.host.onTextCommand?.("number");
|
|
22951
|
+
return;
|
|
22952
|
+
}
|
|
22953
|
+
if (!e.shiftKey && (k === "l" || k === "e" || k === "r" || k === "j")) {
|
|
22954
|
+
e.preventDefault();
|
|
22955
|
+
this.host.onTextCommand?.(
|
|
22956
|
+
k === "l" ? "alignLeft" : k === "e" ? "alignCenter" : k === "r" ? "alignRight" : "justify"
|
|
22957
|
+
);
|
|
22958
|
+
return;
|
|
22959
|
+
}
|
|
22468
22960
|
if (e.key.startsWith("Arrow")) {
|
|
22469
22961
|
e.preventDefault();
|
|
22470
22962
|
const extend = e.shiftKey;
|
|
@@ -23100,6 +23592,7 @@ var _DocxEditor = class _DocxEditor {
|
|
|
23100
23592
|
c.addEventListener("copy", this.onCopy);
|
|
23101
23593
|
c.addEventListener("cut", this.onCut);
|
|
23102
23594
|
c.addEventListener("paste", this.onPaste);
|
|
23595
|
+
c.addEventListener("contextmenu", this.onContextMenu);
|
|
23103
23596
|
c.addEventListener("dragover", this.onDragOver);
|
|
23104
23597
|
c.addEventListener("drop", this.onDrop);
|
|
23105
23598
|
this.applyHfChrome();
|
|
@@ -23119,8 +23612,10 @@ var _DocxEditor = class _DocxEditor {
|
|
|
23119
23612
|
c.removeEventListener("copy", this.onCopy);
|
|
23120
23613
|
c.removeEventListener("cut", this.onCut);
|
|
23121
23614
|
c.removeEventListener("paste", this.onPaste);
|
|
23615
|
+
c.removeEventListener("contextmenu", this.onContextMenu);
|
|
23122
23616
|
c.removeEventListener("dragover", this.onDragOver);
|
|
23123
23617
|
c.removeEventListener("drop", this.onDrop);
|
|
23618
|
+
this.dismissTextContextMenu();
|
|
23124
23619
|
this.dismissSuggestionPopover();
|
|
23125
23620
|
this.setDrawingTool(null);
|
|
23126
23621
|
this.deselectInkGroup();
|
|
@@ -23990,23 +24485,73 @@ var _DocxEditor = class _DocxEditor {
|
|
|
23990
24485
|
};
|
|
23991
24486
|
extra("Alt", "Alternative text", () => {
|
|
23992
24487
|
const cur = imageAltText(src);
|
|
23993
|
-
|
|
23994
|
-
|
|
23995
|
-
|
|
23996
|
-
|
|
23997
|
-
|
|
24488
|
+
void requestTextInputDialog(this.host.container, {
|
|
24489
|
+
title: "Alternative text",
|
|
24490
|
+
label: "Describe this object for screen readers",
|
|
24491
|
+
value: cur
|
|
24492
|
+
}).then((next) => {
|
|
24493
|
+
if (next === null) return;
|
|
24494
|
+
this.host.history?.checkpoint();
|
|
24495
|
+
if (setImageAltText(this.host.doc, src, next)) this.host.rerender();
|
|
24496
|
+
this.deselectImage();
|
|
24497
|
+
});
|
|
23998
24498
|
});
|
|
23999
24499
|
extra("Size", "Exact size (px)", () => {
|
|
24000
24500
|
const curW = parseFloat(el16.style.width) || 0;
|
|
24001
24501
|
const curH = parseFloat(el16.style.height) || 0;
|
|
24002
24502
|
const cur = `${Math.round(curW)}x${Math.round(curH)}`;
|
|
24003
|
-
|
|
24004
|
-
|
|
24005
|
-
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
24503
|
+
void requestTextInputDialog(this.host.container, {
|
|
24504
|
+
title: "Exact size",
|
|
24505
|
+
label: "Width \xD7 height in pixels",
|
|
24506
|
+
value: cur,
|
|
24507
|
+
placeholder: "640 \xD7 360"
|
|
24508
|
+
}).then((next) => {
|
|
24509
|
+
const match = next && /^\s*(\d+)\s*[x×]\s*(\d+)\s*$/i.exec(next);
|
|
24510
|
+
if (!match) return;
|
|
24511
|
+
this.host.history?.checkpoint();
|
|
24512
|
+
if (resizeDrawing(this.host.doc, src, parseInt(match[1], 10), parseInt(match[2], 10))) this.host.rerender();
|
|
24513
|
+
this.deselectImage();
|
|
24514
|
+
});
|
|
24515
|
+
});
|
|
24516
|
+
extra("Position", "Exact page position (px)", () => {
|
|
24517
|
+
const curX = parseFloat(el16.style.left) || 0;
|
|
24518
|
+
const curY = parseFloat(el16.style.top) || 0;
|
|
24519
|
+
void requestTextInputDialog(this.host.container, {
|
|
24520
|
+
title: "Page position",
|
|
24521
|
+
label: "X, Y in pixels",
|
|
24522
|
+
value: `${Math.round(curX)}, ${Math.round(curY)}`,
|
|
24523
|
+
placeholder: "120, 80"
|
|
24524
|
+
}).then((next) => {
|
|
24525
|
+
const match = next && /^\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*$/.exec(next);
|
|
24526
|
+
if (!match) return;
|
|
24527
|
+
this.host.history?.checkpoint();
|
|
24528
|
+
if (!isFloatingDrawing(src)) setImageWrap(this.host.doc, src, "square", { x: 0, y: 0 });
|
|
24529
|
+
if (setFloatingPagePosition(this.host.doc, src, parseFloat(match[1]), parseFloat(match[2]))) {
|
|
24530
|
+
this.host.rerender();
|
|
24531
|
+
this.reselectImage(src);
|
|
24532
|
+
}
|
|
24533
|
+
});
|
|
24009
24534
|
});
|
|
24535
|
+
if (kind === "drawing") {
|
|
24536
|
+
extra("Outline", "Outline color and weight", () => {
|
|
24537
|
+
const style = drawingLineStyle(src);
|
|
24538
|
+
if (!style) return;
|
|
24539
|
+
void requestTextInputDialog(this.host.container, {
|
|
24540
|
+
title: "Outline",
|
|
24541
|
+
label: "Color and width in pixels",
|
|
24542
|
+
value: `${style.color}, ${Number(style.width.toFixed(2))}`,
|
|
24543
|
+
placeholder: "#1a73e8, 1.5"
|
|
24544
|
+
}).then((next) => {
|
|
24545
|
+
const match = next && /^\s*#?([0-9a-f]{6})\s*,\s*(\d+(?:\.\d+)?)\s*$/i.exec(next);
|
|
24546
|
+
if (!match) return;
|
|
24547
|
+
this.host.history?.checkpoint();
|
|
24548
|
+
if (setDrawingLineStyle(this.host.doc, src, `#${match[1]}`, parseFloat(match[2]))) {
|
|
24549
|
+
this.host.rerender();
|
|
24550
|
+
this.reselectImage(src);
|
|
24551
|
+
}
|
|
24552
|
+
});
|
|
24553
|
+
});
|
|
24554
|
+
}
|
|
24010
24555
|
if (kind === "drawing" && isDrawingWordArt(src)) {
|
|
24011
24556
|
extra("Edit text", "Edit WordArt text", () => this.editDrawingWordArt(src));
|
|
24012
24557
|
}
|
|
@@ -24160,13 +24705,17 @@ var _DocxEditor = class _DocxEditor {
|
|
|
24160
24705
|
};
|
|
24161
24706
|
button("Edit text", "Edit watermark text", () => {
|
|
24162
24707
|
const cur = wordArtText(src);
|
|
24163
|
-
|
|
24164
|
-
|
|
24165
|
-
|
|
24166
|
-
|
|
24167
|
-
|
|
24168
|
-
this.
|
|
24169
|
-
|
|
24708
|
+
void requestTextInputDialog(this.host.container, {
|
|
24709
|
+
title: "Watermark text",
|
|
24710
|
+
value: cur
|
|
24711
|
+
}).then((next) => {
|
|
24712
|
+
if (next === null || next === cur) return;
|
|
24713
|
+
this.host.history?.checkpoint();
|
|
24714
|
+
if (setWordArtText(this.host.doc, src, next)) {
|
|
24715
|
+
this.host.rerender();
|
|
24716
|
+
this.reselectWordArt(src);
|
|
24717
|
+
}
|
|
24718
|
+
});
|
|
24170
24719
|
});
|
|
24171
24720
|
const sep1 = document.createElement("span");
|
|
24172
24721
|
sep1.style.cssText = "width:1px;background:#dadce0;margin:2px 2px;";
|
|
@@ -24178,15 +24727,20 @@ var _DocxEditor = class _DocxEditor {
|
|
|
24178
24727
|
bar.appendChild(sep2);
|
|
24179
24728
|
button("Rotate", "Set rotation (degrees)", () => {
|
|
24180
24729
|
const cur = wordArtRotation(src);
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24184
|
-
|
|
24185
|
-
|
|
24186
|
-
|
|
24187
|
-
|
|
24188
|
-
|
|
24189
|
-
|
|
24730
|
+
void requestTextInputDialog(this.host.container, {
|
|
24731
|
+
title: "Watermark rotation",
|
|
24732
|
+
label: "Degrees clockwise",
|
|
24733
|
+
value: String(cur)
|
|
24734
|
+
}).then((next) => {
|
|
24735
|
+
if (next === null) return;
|
|
24736
|
+
const degrees = parseFloat(next);
|
|
24737
|
+
if (!Number.isFinite(degrees)) return;
|
|
24738
|
+
this.host.history?.checkpoint();
|
|
24739
|
+
if (setWordArtRotation(this.host.doc, src, degrees)) {
|
|
24740
|
+
this.host.rerender();
|
|
24741
|
+
this.reselectWordArt(src);
|
|
24742
|
+
}
|
|
24743
|
+
});
|
|
24190
24744
|
});
|
|
24191
24745
|
const sep3 = document.createElement("span");
|
|
24192
24746
|
sep3.style.cssText = "width:1px;background:#dadce0;margin:2px 2px;";
|
|
@@ -25034,16 +25588,19 @@ var _DocxEditor = class _DocxEditor {
|
|
|
25034
25588
|
};
|
|
25035
25589
|
const split = this.splitParagraphCore();
|
|
25036
25590
|
if (!split) return null;
|
|
25037
|
-
const
|
|
25591
|
+
const hasPageBreak = (element) => localName(element.name) === "br" && attr(element, "type") === "page" || element.children.some(hasPageBreak);
|
|
25592
|
+
const insertBeforeTrailingBreak = hasPageBreak(split.after);
|
|
25593
|
+
const afterSources = insertBeforeTrailingBreak ? [] : [split.after];
|
|
25038
25594
|
const w = split.after.name.includes(":") ? split.after.name.slice(0, split.after.name.indexOf(":") + 1) : "";
|
|
25039
25595
|
const templatePPr = split.after.children.find((child4) => localName(child4.name) === "pPr");
|
|
25040
25596
|
const templateRun = split.after.children.find(
|
|
25041
25597
|
(child4) => localName(child4.name) === "r" && child4.children.includes(this.caret.t)
|
|
25042
25598
|
);
|
|
25043
25599
|
const templateRPr = templateRun?.children.find((child4) => localName(child4.name) === "rPr");
|
|
25044
|
-
let previous = split.after;
|
|
25600
|
+
let previous = insertBeforeTrailingBreak ? split.before : split.after;
|
|
25601
|
+
let caretSource = split.after;
|
|
25045
25602
|
for (let i = 1; i < lineCount; i++) {
|
|
25046
|
-
if (this.suggesting) markParagraphGlyph(previous, "ins", this.revMeta());
|
|
25603
|
+
if (this.suggesting && previous !== split.before) markParagraphGlyph(previous, "ins", this.revMeta());
|
|
25047
25604
|
const t = {
|
|
25048
25605
|
name: this.caret.t.name,
|
|
25049
25606
|
attrs: { ...this.caret.t.attrs, "xml:space": "preserve" },
|
|
@@ -25066,11 +25623,14 @@ var _DocxEditor = class _DocxEditor {
|
|
|
25066
25623
|
parent.children.splice(previousIndex + 1, 0, paragraph2);
|
|
25067
25624
|
afterSources.push(paragraph2);
|
|
25068
25625
|
previous = paragraph2;
|
|
25626
|
+
caretSource = paragraph2;
|
|
25069
25627
|
this.caret = { t, run: caret.run, offset: 0 };
|
|
25070
25628
|
}
|
|
25629
|
+
if (insertBeforeTrailingBreak) afterSources.push(split.after);
|
|
25071
25630
|
const reparsed = this.host.doc.reparseDirectBodyParagraphSplits(split.before, afterSources);
|
|
25072
25631
|
if (reparsed) {
|
|
25073
|
-
|
|
25632
|
+
const caretParagraph = reparsed[afterSources.indexOf(caretSource) + 1];
|
|
25633
|
+
for (const child4 of caretParagraph.children) {
|
|
25074
25634
|
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
25075
25635
|
const run = runs.find(
|
|
25076
25636
|
(candidate) => candidate.content.some((content) => content.kind === "text" && content.srcT === this.caret.t)
|
|
@@ -27387,7 +27947,8 @@ function detectMissingFonts(layout) {
|
|
|
27387
27947
|
for (const page of layout.pages) {
|
|
27388
27948
|
for (const item of page.items) {
|
|
27389
27949
|
if (item.kind !== "text" || !item.text.trim()) continue;
|
|
27390
|
-
const
|
|
27950
|
+
const requested = item.font.family.split(",")[0].trim().replace(/^"|"$/g, "");
|
|
27951
|
+
const primary = normalizeFamily(requested, item.font.bold, item.font.italic).family;
|
|
27391
27952
|
if (!primary || GENERIC.has(primary.toLowerCase())) continue;
|
|
27392
27953
|
const existing = samples.get(primary);
|
|
27393
27954
|
if (!existing || !/[^-ɏ]/.test(existing) && /[^-ɏ]/.test(item.text)) {
|
|
@@ -27519,15 +28080,6 @@ var btnStyle = (active) => ({
|
|
|
27519
28080
|
padding: "0 5px",
|
|
27520
28081
|
color: T.fg
|
|
27521
28082
|
});
|
|
27522
|
-
var selectStyle = {
|
|
27523
|
-
height: 26,
|
|
27524
|
-
border: "1px solid transparent",
|
|
27525
|
-
background: "transparent",
|
|
27526
|
-
borderRadius: 4,
|
|
27527
|
-
fontSize: 13,
|
|
27528
|
-
color: T.fg,
|
|
27529
|
-
cursor: "pointer"
|
|
27530
|
-
};
|
|
27531
28083
|
var PAGE_SIZES = [
|
|
27532
28084
|
{ value: "letter", label: "Letter", description: '8.5" \xD7 11"', width: 8.5, height: 11 },
|
|
27533
28085
|
{ value: "legal", label: "Legal", description: '8.5" \xD7 14"', width: 8.5, height: 14 },
|
|
@@ -27631,6 +28183,264 @@ function HighlightIcon({ color }) {
|
|
|
27631
28183
|
/* @__PURE__ */ jsx("rect", { x: "2", y: "13.5", width: "12", height: "2.5", rx: "0.5", fill: color })
|
|
27632
28184
|
] });
|
|
27633
28185
|
}
|
|
28186
|
+
function ToolbarMenuSelect({
|
|
28187
|
+
value,
|
|
28188
|
+
options,
|
|
28189
|
+
onChange,
|
|
28190
|
+
placeholder = "Choose\u2026",
|
|
28191
|
+
title,
|
|
28192
|
+
ariaLabel,
|
|
28193
|
+
triggerAriaLabel,
|
|
28194
|
+
width,
|
|
28195
|
+
menuWidth,
|
|
28196
|
+
className,
|
|
28197
|
+
style
|
|
28198
|
+
}) {
|
|
28199
|
+
const [open, setOpen] = useState(false);
|
|
28200
|
+
const [position, setPosition] = useState({ left: 8, top: 8, width: menuWidth ?? 180, maxHeight: 320 });
|
|
28201
|
+
const rootRef = useRef(null);
|
|
28202
|
+
const triggerRef = useRef(null);
|
|
28203
|
+
const menuRef = useRef(null);
|
|
28204
|
+
const keyboardOpen = useRef(null);
|
|
28205
|
+
const id = useId();
|
|
28206
|
+
const selected = options.find((option) => option.value === value);
|
|
28207
|
+
useLayoutEffect(() => {
|
|
28208
|
+
if (!open) return;
|
|
28209
|
+
const update = () => {
|
|
28210
|
+
const trigger = triggerRef.current;
|
|
28211
|
+
if (!trigger) return;
|
|
28212
|
+
const rect = trigger.getBoundingClientRect();
|
|
28213
|
+
const nextWidth = Math.min(
|
|
28214
|
+
window.innerWidth - 16,
|
|
28215
|
+
menuWidth ?? Math.max(rect.width, menuRef.current?.scrollWidth ?? 180)
|
|
28216
|
+
);
|
|
28217
|
+
const below = window.innerHeight - rect.bottom - 8;
|
|
28218
|
+
const above = rect.top - 8;
|
|
28219
|
+
const placeAbove = below < 140 && above > below;
|
|
28220
|
+
const maxHeight = Math.max(96, Math.min(320, placeAbove ? above : below));
|
|
28221
|
+
const shownHeight = Math.min(menuRef.current?.scrollHeight ?? maxHeight, maxHeight);
|
|
28222
|
+
setPosition({
|
|
28223
|
+
left: Math.max(8, Math.min(rect.left, window.innerWidth - nextWidth - 8)),
|
|
28224
|
+
top: placeAbove ? Math.max(8, rect.top - shownHeight - 4) : rect.bottom + 4,
|
|
28225
|
+
width: nextWidth,
|
|
28226
|
+
maxHeight
|
|
28227
|
+
});
|
|
28228
|
+
};
|
|
28229
|
+
update();
|
|
28230
|
+
const frame = requestAnimationFrame(() => {
|
|
28231
|
+
update();
|
|
28232
|
+
if (!keyboardOpen.current) return;
|
|
28233
|
+
const items = menuRef.current?.querySelectorAll('[role="option"]');
|
|
28234
|
+
const item = keyboardOpen.current === "last" ? items?.[items.length - 1] : items?.[0];
|
|
28235
|
+
item?.focus({ preventScroll: true });
|
|
28236
|
+
keyboardOpen.current = null;
|
|
28237
|
+
});
|
|
28238
|
+
const close = (event) => {
|
|
28239
|
+
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
28240
|
+
};
|
|
28241
|
+
const keydown = (event) => {
|
|
28242
|
+
if (event.key === "Escape") {
|
|
28243
|
+
setOpen(false);
|
|
28244
|
+
requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
28245
|
+
}
|
|
28246
|
+
};
|
|
28247
|
+
document.addEventListener("mousedown", close);
|
|
28248
|
+
document.addEventListener("keydown", keydown);
|
|
28249
|
+
window.addEventListener("resize", update);
|
|
28250
|
+
window.addEventListener("scroll", update, true);
|
|
28251
|
+
return () => {
|
|
28252
|
+
cancelAnimationFrame(frame);
|
|
28253
|
+
document.removeEventListener("mousedown", close);
|
|
28254
|
+
document.removeEventListener("keydown", keydown);
|
|
28255
|
+
window.removeEventListener("resize", update);
|
|
28256
|
+
window.removeEventListener("scroll", update, true);
|
|
28257
|
+
};
|
|
28258
|
+
}, [open, menuWidth]);
|
|
28259
|
+
const pick = (next) => {
|
|
28260
|
+
const option = options.find((item) => item.value === next);
|
|
28261
|
+
if (!option || option.disabled) return;
|
|
28262
|
+
onChange(next);
|
|
28263
|
+
setOpen(false);
|
|
28264
|
+
};
|
|
28265
|
+
const onMenuKeyDown = (event) => {
|
|
28266
|
+
const items = menuRef.current ? Array.from(menuRef.current.querySelectorAll('[role="option"]:not(:disabled)')) : [];
|
|
28267
|
+
const current = items.indexOf(document.activeElement);
|
|
28268
|
+
let next = current;
|
|
28269
|
+
if (event.key === "ArrowDown") next = current < 0 ? 0 : (current + 1) % items.length;
|
|
28270
|
+
else if (event.key === "ArrowUp") next = current < 0 ? items.length - 1 : (current - 1 + items.length) % items.length;
|
|
28271
|
+
else if (event.key === "Home") next = 0;
|
|
28272
|
+
else if (event.key === "End") next = items.length - 1;
|
|
28273
|
+
else if ((event.key === "Enter" || event.key === " ") && current >= 0) {
|
|
28274
|
+
event.preventDefault();
|
|
28275
|
+
items[current].click();
|
|
28276
|
+
return;
|
|
28277
|
+
} else if (event.key === "Escape" || event.key === "Tab") {
|
|
28278
|
+
event.preventDefault();
|
|
28279
|
+
setOpen(false);
|
|
28280
|
+
requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
28281
|
+
return;
|
|
28282
|
+
} else return;
|
|
28283
|
+
event.preventDefault();
|
|
28284
|
+
items[next]?.focus({ preventScroll: true });
|
|
28285
|
+
};
|
|
28286
|
+
let previousGroup;
|
|
28287
|
+
return /* @__PURE__ */ jsxs(
|
|
28288
|
+
"span",
|
|
28289
|
+
{
|
|
28290
|
+
ref: rootRef,
|
|
28291
|
+
className: `dxw-menu-select${className ? ` ${className}` : ""}`,
|
|
28292
|
+
"data-dxw-menu-select": "",
|
|
28293
|
+
style: { position: "relative", display: "inline-flex", width },
|
|
28294
|
+
children: [
|
|
28295
|
+
/* @__PURE__ */ jsxs(
|
|
28296
|
+
"select",
|
|
28297
|
+
{
|
|
28298
|
+
tabIndex: -1,
|
|
28299
|
+
title,
|
|
28300
|
+
"aria-label": ariaLabel,
|
|
28301
|
+
"aria-hidden": "true",
|
|
28302
|
+
value,
|
|
28303
|
+
onChange: (event) => pick(event.target.value),
|
|
28304
|
+
"data-dxw-native-bridge": "",
|
|
28305
|
+
style: {
|
|
28306
|
+
position: "absolute",
|
|
28307
|
+
width: 1,
|
|
28308
|
+
height: 1,
|
|
28309
|
+
inset: 0,
|
|
28310
|
+
opacity: 0,
|
|
28311
|
+
pointerEvents: "none"
|
|
28312
|
+
},
|
|
28313
|
+
children: [
|
|
28314
|
+
!options.some((option) => option.value === value) && /* @__PURE__ */ jsx("option", { value: "", children: String(placeholder) }),
|
|
28315
|
+
options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, disabled: option.disabled, children: String(option.label) }, option.value))
|
|
28316
|
+
]
|
|
28317
|
+
}
|
|
28318
|
+
),
|
|
28319
|
+
/* @__PURE__ */ jsxs(
|
|
28320
|
+
"button",
|
|
28321
|
+
{
|
|
28322
|
+
ref: triggerRef,
|
|
28323
|
+
type: "button",
|
|
28324
|
+
"aria-haspopup": "listbox",
|
|
28325
|
+
"aria-expanded": open,
|
|
28326
|
+
"aria-controls": open ? id : void 0,
|
|
28327
|
+
"aria-label": triggerAriaLabel,
|
|
28328
|
+
"data-tip": title,
|
|
28329
|
+
className: "dxw-menu-select-trigger",
|
|
28330
|
+
"data-dxw-menu-select-trigger": "",
|
|
28331
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28332
|
+
onClick: () => setOpen(!open),
|
|
28333
|
+
onKeyDown: (event) => {
|
|
28334
|
+
if (!open && (event.key === "Enter" || event.key === " " || event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
28335
|
+
event.preventDefault();
|
|
28336
|
+
keyboardOpen.current = event.key === "ArrowUp" ? "last" : "first";
|
|
28337
|
+
setOpen(true);
|
|
28338
|
+
}
|
|
28339
|
+
},
|
|
28340
|
+
style: {
|
|
28341
|
+
width: "100%",
|
|
28342
|
+
minWidth: 0,
|
|
28343
|
+
height: "var(--dxw-select-height, 26px)",
|
|
28344
|
+
border: "1px solid var(--dxw-select-border, transparent)",
|
|
28345
|
+
borderRadius: "var(--dxw-select-radius, 4px)",
|
|
28346
|
+
background: "var(--dxw-select-bg, transparent)",
|
|
28347
|
+
color: "var(--dxw-select-fg, var(--dxw-toolbar-fg, #3c4043))",
|
|
28348
|
+
padding: "var(--dxw-select-padding, 0 6px)",
|
|
28349
|
+
display: "inline-flex",
|
|
28350
|
+
alignItems: "center",
|
|
28351
|
+
justifyContent: "space-between",
|
|
28352
|
+
gap: 6,
|
|
28353
|
+
cursor: "pointer",
|
|
28354
|
+
font: "var(--dxw-select-font, 13px system-ui, sans-serif)",
|
|
28355
|
+
...style
|
|
28356
|
+
},
|
|
28357
|
+
children: [
|
|
28358
|
+
/* @__PURE__ */ jsx("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontFamily: selected?.fontFamily }, children: selected?.label ?? placeholder }),
|
|
28359
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "dxw-menu-select-chevron", style: { flexShrink: 0, fontSize: 10 }, children: "\u2304" })
|
|
28360
|
+
]
|
|
28361
|
+
}
|
|
28362
|
+
),
|
|
28363
|
+
open && /* @__PURE__ */ jsx(
|
|
28364
|
+
"div",
|
|
28365
|
+
{
|
|
28366
|
+
ref: menuRef,
|
|
28367
|
+
id,
|
|
28368
|
+
role: "listbox",
|
|
28369
|
+
"aria-label": ariaLabel ?? title,
|
|
28370
|
+
className: "dxw-menu-select-menu",
|
|
28371
|
+
"data-dxw-menu-select-menu": "",
|
|
28372
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28373
|
+
onKeyDown: onMenuKeyDown,
|
|
28374
|
+
style: {
|
|
28375
|
+
position: "fixed",
|
|
28376
|
+
left: position.left,
|
|
28377
|
+
top: position.top,
|
|
28378
|
+
zIndex: "var(--dxw-toolbar-z-index, 100)",
|
|
28379
|
+
width: position.width,
|
|
28380
|
+
maxHeight: `min(var(--dxw-select-menu-max-height, 320px), ${position.maxHeight}px)`,
|
|
28381
|
+
overflowY: "auto",
|
|
28382
|
+
overscrollBehavior: "contain",
|
|
28383
|
+
boxSizing: "border-box",
|
|
28384
|
+
padding: "var(--dxw-select-menu-padding, 5px)",
|
|
28385
|
+
border: "1px solid var(--dxw-select-menu-border, var(--dxw-toolbar-border, #dadce0))",
|
|
28386
|
+
borderRadius: "var(--dxw-select-menu-radius, 8px)",
|
|
28387
|
+
background: "var(--dxw-select-menu-bg, var(--dxw-popover-bg, #fff))",
|
|
28388
|
+
boxShadow: "var(--dxw-select-menu-shadow, var(--dxw-popover-shadow, 0 4px 16px rgba(0,0,0,.15)))"
|
|
28389
|
+
},
|
|
28390
|
+
children: options.map((option) => {
|
|
28391
|
+
const groupChanged = option.group !== previousGroup;
|
|
28392
|
+
previousGroup = option.group;
|
|
28393
|
+
const active = option.value === value;
|
|
28394
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
28395
|
+
groupChanged && option.group && /* @__PURE__ */ jsx("div", { className: "dxw-menu-select-group", style: { padding: "6px 8px 3px", color: T.muted, font: "600 10.5px system-ui, sans-serif" }, children: option.group }),
|
|
28396
|
+
/* @__PURE__ */ jsxs(
|
|
28397
|
+
"button",
|
|
28398
|
+
{
|
|
28399
|
+
type: "button",
|
|
28400
|
+
role: "option",
|
|
28401
|
+
"aria-selected": active,
|
|
28402
|
+
disabled: option.disabled,
|
|
28403
|
+
tabIndex: -1,
|
|
28404
|
+
className: "dxw-menu-select-option",
|
|
28405
|
+
"data-dxw-menu-select-option": option.value,
|
|
28406
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28407
|
+
onClick: () => pick(option.value),
|
|
28408
|
+
style: {
|
|
28409
|
+
width: "100%",
|
|
28410
|
+
minHeight: 30,
|
|
28411
|
+
border: 0,
|
|
28412
|
+
borderRadius: 6,
|
|
28413
|
+
padding: "5px 8px",
|
|
28414
|
+
display: "flex",
|
|
28415
|
+
alignItems: "center",
|
|
28416
|
+
gap: 8,
|
|
28417
|
+
background: active ? T.activeBg : "transparent",
|
|
28418
|
+
color: option.disabled ? T.muted : T.fg,
|
|
28419
|
+
textAlign: "left",
|
|
28420
|
+
cursor: option.disabled ? "default" : "pointer",
|
|
28421
|
+
font: "13px system-ui, sans-serif",
|
|
28422
|
+
fontFamily: option.fontFamily
|
|
28423
|
+
},
|
|
28424
|
+
onMouseEnter: (event) => {
|
|
28425
|
+
if (!active && !option.disabled) event.currentTarget.style.background = T.hoverBg;
|
|
28426
|
+
},
|
|
28427
|
+
onMouseLeave: (event) => {
|
|
28428
|
+
if (!active) event.currentTarget.style.background = "transparent";
|
|
28429
|
+
},
|
|
28430
|
+
children: [
|
|
28431
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: option.label }),
|
|
28432
|
+
active && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { color: T.accent, fontWeight: 700 }, children: "\u2713" })
|
|
28433
|
+
]
|
|
28434
|
+
}
|
|
28435
|
+
)
|
|
28436
|
+
] }, option.value);
|
|
28437
|
+
})
|
|
28438
|
+
}
|
|
28439
|
+
)
|
|
28440
|
+
]
|
|
28441
|
+
}
|
|
28442
|
+
);
|
|
28443
|
+
}
|
|
27634
28444
|
function ActionMenu({
|
|
27635
28445
|
label,
|
|
27636
28446
|
title,
|
|
@@ -27638,22 +28448,21 @@ function ActionMenu({
|
|
|
27638
28448
|
onPick,
|
|
27639
28449
|
width
|
|
27640
28450
|
}) {
|
|
27641
|
-
return /* @__PURE__ */
|
|
27642
|
-
|
|
28451
|
+
return /* @__PURE__ */ jsx(
|
|
28452
|
+
ToolbarMenuSelect,
|
|
27643
28453
|
{
|
|
27644
28454
|
title,
|
|
28455
|
+
triggerAriaLabel: title,
|
|
27645
28456
|
value: "",
|
|
27646
|
-
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
|
|
27650
|
-
|
|
27651
|
-
|
|
27652
|
-
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
)
|
|
27656
|
-
]
|
|
28457
|
+
placeholder: label,
|
|
28458
|
+
width,
|
|
28459
|
+
menuWidth: Math.max(width ?? 0, 190),
|
|
28460
|
+
options: groups.flatMap((group) => group.items.map(([value, text]) => ({
|
|
28461
|
+
value,
|
|
28462
|
+
label: text,
|
|
28463
|
+
group: group.label
|
|
28464
|
+
}))),
|
|
28465
|
+
onChange: onPick
|
|
27657
28466
|
}
|
|
27658
28467
|
);
|
|
27659
28468
|
}
|
|
@@ -27733,6 +28542,183 @@ function HighlightMenu({ current, onPick }) {
|
|
|
27733
28542
|
)
|
|
27734
28543
|
] });
|
|
27735
28544
|
}
|
|
28545
|
+
var COLOR_SWATCHES = [
|
|
28546
|
+
"#000000",
|
|
28547
|
+
"#434343",
|
|
28548
|
+
"#666666",
|
|
28549
|
+
"#999999",
|
|
28550
|
+
"#b7b7b7",
|
|
28551
|
+
"#cccccc",
|
|
28552
|
+
"#d9d9d9",
|
|
28553
|
+
"#ffffff",
|
|
28554
|
+
"#980000",
|
|
28555
|
+
"#ff0000",
|
|
28556
|
+
"#ff9900",
|
|
28557
|
+
"#ffff00",
|
|
28558
|
+
"#00ff00",
|
|
28559
|
+
"#00ffff",
|
|
28560
|
+
"#4a86e8",
|
|
28561
|
+
"#0000ff",
|
|
28562
|
+
"#9900ff",
|
|
28563
|
+
"#ff00ff",
|
|
28564
|
+
"#e6b8af",
|
|
28565
|
+
"#f4cccc",
|
|
28566
|
+
"#fce5cd",
|
|
28567
|
+
"#fff2cc",
|
|
28568
|
+
"#d9ead3",
|
|
28569
|
+
"#d0e0e3",
|
|
28570
|
+
"#c9daf8",
|
|
28571
|
+
"#cfe2f3",
|
|
28572
|
+
"#d9d2e9",
|
|
28573
|
+
"#ead1dc",
|
|
28574
|
+
"#a61c00",
|
|
28575
|
+
"#cc0000",
|
|
28576
|
+
"#e69138",
|
|
28577
|
+
"#6aa84f"
|
|
28578
|
+
];
|
|
28579
|
+
function normalizedColor(value) {
|
|
28580
|
+
const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value.trim());
|
|
28581
|
+
if (!match) return null;
|
|
28582
|
+
const digits = match[1].length === 3 ? match[1].split("").map((digit) => digit + digit).join("") : match[1];
|
|
28583
|
+
return `#${digits.toLowerCase()}`;
|
|
28584
|
+
}
|
|
28585
|
+
function ColorMenu({
|
|
28586
|
+
current,
|
|
28587
|
+
title,
|
|
28588
|
+
trigger,
|
|
28589
|
+
onPick
|
|
28590
|
+
}) {
|
|
28591
|
+
const [open, setOpen] = useState(false);
|
|
28592
|
+
const [custom, setCustom] = useState(current);
|
|
28593
|
+
const [position, setPosition] = useState({ left: 8, top: 8 });
|
|
28594
|
+
const rootRef = useRef(null);
|
|
28595
|
+
const triggerRef = useRef(null);
|
|
28596
|
+
const menuRef = useRef(null);
|
|
28597
|
+
const valid = normalizedColor(custom);
|
|
28598
|
+
useLayoutEffect(() => {
|
|
28599
|
+
if (!open) return;
|
|
28600
|
+
setCustom(current);
|
|
28601
|
+
const update = () => {
|
|
28602
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
28603
|
+
if (!rect) return;
|
|
28604
|
+
const width = Math.min(236, window.innerWidth - 16);
|
|
28605
|
+
const menuHeight = menuRef.current?.offsetHeight ?? 188;
|
|
28606
|
+
const top = window.innerHeight - rect.bottom >= menuHeight + 8 ? rect.bottom + 4 : Math.max(8, rect.top - menuHeight - 4);
|
|
28607
|
+
setPosition({ left: Math.max(8, Math.min(rect.left, window.innerWidth - width - 8)), top });
|
|
28608
|
+
};
|
|
28609
|
+
update();
|
|
28610
|
+
const frame = requestAnimationFrame(update);
|
|
28611
|
+
const close = (event) => {
|
|
28612
|
+
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
28613
|
+
};
|
|
28614
|
+
const keydown = (event) => {
|
|
28615
|
+
if (event.key === "Escape") {
|
|
28616
|
+
setOpen(false);
|
|
28617
|
+
requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
28618
|
+
}
|
|
28619
|
+
};
|
|
28620
|
+
document.addEventListener("mousedown", close);
|
|
28621
|
+
document.addEventListener("keydown", keydown);
|
|
28622
|
+
window.addEventListener("resize", update);
|
|
28623
|
+
window.addEventListener("scroll", update, true);
|
|
28624
|
+
return () => {
|
|
28625
|
+
cancelAnimationFrame(frame);
|
|
28626
|
+
document.removeEventListener("mousedown", close);
|
|
28627
|
+
document.removeEventListener("keydown", keydown);
|
|
28628
|
+
window.removeEventListener("resize", update);
|
|
28629
|
+
window.removeEventListener("scroll", update, true);
|
|
28630
|
+
};
|
|
28631
|
+
}, [open, current]);
|
|
28632
|
+
const pick = (value) => {
|
|
28633
|
+
onPick(value);
|
|
28634
|
+
setOpen(false);
|
|
28635
|
+
};
|
|
28636
|
+
return /* @__PURE__ */ jsxs("span", { ref: rootRef, className: "dxw-color-control", style: { position: "relative", display: "inline-flex" }, children: [
|
|
28637
|
+
/* @__PURE__ */ jsx(
|
|
28638
|
+
"button",
|
|
28639
|
+
{
|
|
28640
|
+
ref: triggerRef,
|
|
28641
|
+
type: "button",
|
|
28642
|
+
title,
|
|
28643
|
+
"aria-haspopup": "dialog",
|
|
28644
|
+
"aria-expanded": open,
|
|
28645
|
+
className: "dxw-color-trigger",
|
|
28646
|
+
"data-dxw-color-trigger": "",
|
|
28647
|
+
style: { ...btnStyle(open), display: "inline-flex", alignItems: "center", gap: 5 },
|
|
28648
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28649
|
+
onClick: () => setOpen(!open),
|
|
28650
|
+
children: trigger
|
|
28651
|
+
}
|
|
28652
|
+
),
|
|
28653
|
+
open && /* @__PURE__ */ jsxs(
|
|
28654
|
+
"div",
|
|
28655
|
+
{
|
|
28656
|
+
ref: menuRef,
|
|
28657
|
+
role: "dialog",
|
|
28658
|
+
"aria-label": title,
|
|
28659
|
+
className: "dxw-color-menu",
|
|
28660
|
+
"data-dxw-color-menu": "",
|
|
28661
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
28662
|
+
style: {
|
|
28663
|
+
position: "fixed",
|
|
28664
|
+
left: position.left,
|
|
28665
|
+
top: position.top,
|
|
28666
|
+
zIndex: "var(--dxw-toolbar-z-index, 100)",
|
|
28667
|
+
width: "min(var(--dxw-color-menu-width, 236px), calc(100vw - 16px))",
|
|
28668
|
+
boxSizing: "border-box",
|
|
28669
|
+
padding: 8,
|
|
28670
|
+
border: `1px solid ${T.border}`,
|
|
28671
|
+
borderRadius: 8,
|
|
28672
|
+
background: T.popoverBg,
|
|
28673
|
+
boxShadow: T.popoverShadow
|
|
28674
|
+
},
|
|
28675
|
+
children: [
|
|
28676
|
+
/* @__PURE__ */ jsx("div", { className: "dxw-color-swatches", style: { display: "grid", gridTemplateColumns: "repeat(8, 1fr)", gap: 4 }, children: COLOR_SWATCHES.map((color) => /* @__PURE__ */ jsx(
|
|
28677
|
+
"button",
|
|
28678
|
+
{
|
|
28679
|
+
type: "button",
|
|
28680
|
+
title: color,
|
|
28681
|
+
"aria-label": `Choose ${color}`,
|
|
28682
|
+
className: "dxw-color-swatch",
|
|
28683
|
+
"data-dxw-color": color,
|
|
28684
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28685
|
+
onClick: () => pick(color),
|
|
28686
|
+
style: {
|
|
28687
|
+
width: 23,
|
|
28688
|
+
height: 23,
|
|
28689
|
+
padding: 0,
|
|
28690
|
+
borderRadius: 4,
|
|
28691
|
+
cursor: "pointer",
|
|
28692
|
+
border: color.toLowerCase() === current.toLowerCase() ? `2px solid ${T.accent}` : `1px solid ${T.border}`,
|
|
28693
|
+
background: color
|
|
28694
|
+
}
|
|
28695
|
+
},
|
|
28696
|
+
color
|
|
28697
|
+
)) }),
|
|
28698
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginTop: 8 }, children: [
|
|
28699
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { width: 24, height: 24, borderRadius: 4, border: `1px solid ${T.border}`, background: valid ?? current, flexShrink: 0 } }),
|
|
28700
|
+
/* @__PURE__ */ jsx(
|
|
28701
|
+
"input",
|
|
28702
|
+
{
|
|
28703
|
+
"aria-label": "Custom hex color",
|
|
28704
|
+
className: "dxw-color-value",
|
|
28705
|
+
value: custom,
|
|
28706
|
+
onChange: (event) => setCustom(event.target.value),
|
|
28707
|
+
onKeyDown: (event) => {
|
|
28708
|
+
if (event.key === "Enter" && valid) pick(valid);
|
|
28709
|
+
},
|
|
28710
|
+
spellCheck: false,
|
|
28711
|
+
placeholder: "#1a73e8",
|
|
28712
|
+
style: { minWidth: 0, flex: 1, height: 28, boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 5, padding: "3px 6px", color: T.fg, background: T.popoverBg }
|
|
28713
|
+
}
|
|
28714
|
+
),
|
|
28715
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled: !valid, onClick: () => valid && pick(valid), style: pillBtn, children: "Apply" })
|
|
28716
|
+
] })
|
|
28717
|
+
]
|
|
28718
|
+
}
|
|
28719
|
+
)
|
|
28720
|
+
] });
|
|
28721
|
+
}
|
|
27736
28722
|
function BulletListIcon() {
|
|
27737
28723
|
return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
|
|
27738
28724
|
/* @__PURE__ */ jsx("circle", { cx: "3", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
|
|
@@ -28095,7 +29081,18 @@ function CrossReferenceMenu({ api }) {
|
|
|
28095
29081
|
return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
28096
29082
|
/* @__PURE__ */ jsx("button", { title: "Insert cross-reference", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cross-reference" }),
|
|
28097
29083
|
open && /* @__PURE__ */ jsx("div", { style: { position: "absolute", top: 28, left: 0, zIndex: 100, width: 260, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: bookmarks.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: T.muted, fontSize: 12 }, children: "Add a bookmark first, then reference its text or page." }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
28098
|
-
/* @__PURE__ */ jsx(
|
|
29084
|
+
/* @__PURE__ */ jsx(
|
|
29085
|
+
ToolbarMenuSelect,
|
|
29086
|
+
{
|
|
29087
|
+
value: selected,
|
|
29088
|
+
ariaLabel: "Bookmark to reference",
|
|
29089
|
+
width: "100%",
|
|
29090
|
+
menuWidth: 240,
|
|
29091
|
+
options: bookmarks.map((name) => ({ value: name, label: name })),
|
|
29092
|
+
onChange: setBookmark,
|
|
29093
|
+
style: { borderColor: T.border }
|
|
29094
|
+
}
|
|
29095
|
+
),
|
|
28099
29096
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
|
|
28100
29097
|
/* @__PURE__ */ jsx("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => insert("page"), children: "Page number" }),
|
|
28101
29098
|
/* @__PURE__ */ jsx("button", { style: pillBtn, onClick: () => insert("text"), children: "Bookmark text" })
|
|
@@ -28202,6 +29199,7 @@ function SymbolMenu({ api }) {
|
|
|
28202
29199
|
] });
|
|
28203
29200
|
}
|
|
28204
29201
|
var SHAPES = [
|
|
29202
|
+
["line", "Line", "\u2015"],
|
|
28205
29203
|
["rectangle", "Rectangle", "\u25AD"],
|
|
28206
29204
|
["roundedRectangle", "Rounded rectangle", "\u25A2"],
|
|
28207
29205
|
["ellipse", "Ellipse", "\u25EF"],
|
|
@@ -28373,12 +29371,23 @@ function ChartMenu({ api }) {
|
|
|
28373
29371
|
return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
28374
29372
|
/* @__PURE__ */ jsx("button", { title: "Insert or edit chart", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Chart" }),
|
|
28375
29373
|
open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 320, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
|
|
28376
|
-
/* @__PURE__ */
|
|
28377
|
-
|
|
28378
|
-
|
|
28379
|
-
|
|
28380
|
-
|
|
28381
|
-
|
|
29374
|
+
/* @__PURE__ */ jsx(
|
|
29375
|
+
ToolbarMenuSelect,
|
|
29376
|
+
{
|
|
29377
|
+
value: type,
|
|
29378
|
+
ariaLabel: "Chart type",
|
|
29379
|
+
width: "100%",
|
|
29380
|
+
menuWidth: 300,
|
|
29381
|
+
options: [
|
|
29382
|
+
{ value: "column", label: "Column" },
|
|
29383
|
+
{ value: "bar", label: "Bar" },
|
|
29384
|
+
{ value: "line", label: "Line" },
|
|
29385
|
+
{ value: "pie", label: "Pie" }
|
|
29386
|
+
],
|
|
29387
|
+
onChange: (value) => setType(value),
|
|
29388
|
+
style: fieldStyle
|
|
29389
|
+
}
|
|
29390
|
+
),
|
|
28382
29391
|
/* @__PURE__ */ jsx("input", { "aria-label": "Chart title", value: title, onChange: (event) => setTitle(event.target.value), placeholder: "Chart title", style: fieldStyle }),
|
|
28383
29392
|
/* @__PURE__ */ jsx("input", { "aria-label": "Chart categories", value: categories, onChange: (event) => setCategories(event.target.value), placeholder: "Q1, Q2, Q3, Q4", style: fieldStyle }),
|
|
28384
29393
|
/* @__PURE__ */ jsx("textarea", { "aria-label": "Chart series", rows: 3, value: series, onChange: (event) => setSeries(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
|
|
@@ -28411,12 +29420,23 @@ function SmartArtMenu({ api }) {
|
|
|
28411
29420
|
return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
28412
29421
|
/* @__PURE__ */ jsx("button", { title: "Insert or edit SmartArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "SmartArt" }),
|
|
28413
29422
|
open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 280, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
|
|
28414
|
-
/* @__PURE__ */
|
|
28415
|
-
|
|
28416
|
-
|
|
28417
|
-
|
|
28418
|
-
|
|
28419
|
-
|
|
29423
|
+
/* @__PURE__ */ jsx(
|
|
29424
|
+
ToolbarMenuSelect,
|
|
29425
|
+
{
|
|
29426
|
+
value: layout,
|
|
29427
|
+
ariaLabel: "SmartArt layout",
|
|
29428
|
+
width: "100%",
|
|
29429
|
+
menuWidth: 260,
|
|
29430
|
+
options: [
|
|
29431
|
+
{ value: "process", label: "Process" },
|
|
29432
|
+
{ value: "cycle", label: "Cycle" },
|
|
29433
|
+
{ value: "hierarchy", label: "Hierarchy" },
|
|
29434
|
+
{ value: "list", label: "List" }
|
|
29435
|
+
],
|
|
29436
|
+
onChange: (value) => setLayout(value),
|
|
29437
|
+
style: fieldStyle
|
|
29438
|
+
}
|
|
29439
|
+
),
|
|
28420
29440
|
/* @__PURE__ */ jsx("textarea", { "aria-label": "SmartArt items", rows: 5, value: items, onChange: (event) => setItems(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
|
|
28421
29441
|
/* @__PURE__ */ jsx("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "One diagram item per line." }),
|
|
28422
29442
|
/* @__PURE__ */ jsx("button", { disabled: !items.trim(), onClick: submit, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: items.trim() ? T.accent : T.border, color: T.accentFg, cursor: items.trim() ? "pointer" : "default", font: "600 12px system-ui, sans-serif" }, children: "Insert or update SmartArt" })
|
|
@@ -28474,19 +29494,18 @@ function DrawTab({ api }) {
|
|
|
28474
29494
|
/* @__PURE__ */ jsx(Btn, { label: "Eraser", title: "Stroke eraser", active: active === "eraser", onClick: () => api?.setDrawingTool({ kind: "eraser", size: 14 }) }),
|
|
28475
29495
|
/* @__PURE__ */ jsx(Btn, { label: "Lasso", title: "Lasso ink", active: active === "lasso", onClick: () => api?.setDrawingTool({ kind: "lasso" }) }),
|
|
28476
29496
|
/* @__PURE__ */ jsx(Sep, {}),
|
|
28477
|
-
/* @__PURE__ */
|
|
28478
|
-
|
|
28479
|
-
|
|
28480
|
-
|
|
28481
|
-
|
|
28482
|
-
|
|
28483
|
-
|
|
28484
|
-
|
|
28485
|
-
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
|
|
28489
|
-
] }),
|
|
29497
|
+
/* @__PURE__ */ jsx(
|
|
29498
|
+
ColorMenu,
|
|
29499
|
+
{
|
|
29500
|
+
current: color,
|
|
29501
|
+
title: "Pen color",
|
|
29502
|
+
trigger: /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
29503
|
+
/* @__PURE__ */ jsx("span", { style: { font: "12px system-ui, sans-serif" }, children: "Color" }),
|
|
29504
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { width: 18, height: 18, borderRadius: 4, border: `1px solid ${T.border}`, background: color } })
|
|
29505
|
+
] }),
|
|
29506
|
+
onPick: (value) => activate(active === "highlighter" ? "highlighter" : "pen", value, width)
|
|
29507
|
+
}
|
|
29508
|
+
),
|
|
28490
29509
|
/* @__PURE__ */ jsx(
|
|
28491
29510
|
ActionMenu,
|
|
28492
29511
|
{
|
|
@@ -29064,9 +30083,8 @@ function MarginMenu({
|
|
|
29064
30083
|
"input",
|
|
29065
30084
|
{
|
|
29066
30085
|
"aria-label": `${label} margin (inches)`,
|
|
29067
|
-
type: "
|
|
29068
|
-
|
|
29069
|
-
step: "0.01",
|
|
30086
|
+
type: "text",
|
|
30087
|
+
inputMode: "decimal",
|
|
29070
30088
|
required: true,
|
|
29071
30089
|
autoFocus: side === "top",
|
|
29072
30090
|
value: values[side],
|
|
@@ -29191,9 +30209,8 @@ function PageSizeMenu({
|
|
|
29191
30209
|
"input",
|
|
29192
30210
|
{
|
|
29193
30211
|
"aria-label": `Page ${side} (inches)`,
|
|
29194
|
-
type: "
|
|
29195
|
-
|
|
29196
|
-
step: "0.01",
|
|
30212
|
+
type: "text",
|
|
30213
|
+
inputMode: "decimal",
|
|
29197
30214
|
required: true,
|
|
29198
30215
|
autoFocus: side === "width",
|
|
29199
30216
|
value: values[side],
|
|
@@ -29291,19 +30308,20 @@ function LayoutTab({ api, showArrange }) {
|
|
|
29291
30308
|
"data-dxw-layout-ribbon": "",
|
|
29292
30309
|
style: { display: "flex", flex: "1 1 640px", minWidth: 0, alignItems: "center", flexWrap: "wrap", gap: 2 },
|
|
29293
30310
|
children: [
|
|
29294
|
-
/* @__PURE__ */
|
|
29295
|
-
|
|
30311
|
+
/* @__PURE__ */ jsx(
|
|
30312
|
+
ToolbarMenuSelect,
|
|
29296
30313
|
{
|
|
29297
30314
|
title: "Apply layout changes to",
|
|
29298
|
-
|
|
30315
|
+
ariaLabel: "Apply layout changes to",
|
|
29299
30316
|
value: scope,
|
|
29300
|
-
|
|
29301
|
-
|
|
29302
|
-
|
|
29303
|
-
|
|
29304
|
-
|
|
29305
|
-
|
|
29306
|
-
|
|
30317
|
+
width: 118,
|
|
30318
|
+
menuWidth: 170,
|
|
30319
|
+
options: [
|
|
30320
|
+
{ value: "document", label: "Whole document" },
|
|
30321
|
+
{ value: "section", label: "This section" }
|
|
30322
|
+
],
|
|
30323
|
+
onChange: (value) => setScope(value),
|
|
30324
|
+
style: { maxWidth: "100%" }
|
|
29307
30325
|
}
|
|
29308
30326
|
),
|
|
29309
30327
|
/* @__PURE__ */ jsx(Sep, {}),
|
|
@@ -29530,42 +30548,44 @@ function DocxToolbar({
|
|
|
29530
30548
|
if (on("styles"))
|
|
29531
30549
|
groups.push({
|
|
29532
30550
|
key: "styles",
|
|
29533
|
-
node: /* @__PURE__ */
|
|
29534
|
-
|
|
30551
|
+
node: /* @__PURE__ */ jsx(
|
|
30552
|
+
ToolbarMenuSelect,
|
|
29535
30553
|
{
|
|
29536
30554
|
title: "Paragraph style",
|
|
29537
30555
|
value: curStyle ?? "__normal",
|
|
29538
|
-
|
|
29539
|
-
|
|
29540
|
-
|
|
29541
|
-
|
|
30556
|
+
width: 92,
|
|
30557
|
+
menuWidth: 190,
|
|
30558
|
+
options: [
|
|
30559
|
+
{ value: "__normal", label: "Normal" },
|
|
30560
|
+
...(api?.listParagraphStyles() ?? []).filter((style2) => !/^normal$/i.test(style2.name)).map((style2) => ({ value: style2.id, label: style2.name })),
|
|
30561
|
+
...curStyle !== null && !(api?.listParagraphStyles() ?? []).some((style2) => style2.id === curStyle) ? [{ value: curStyle, label: api?.document.styles.byId.get(curStyle)?.name ?? curStyle }] : []
|
|
30562
|
+
],
|
|
30563
|
+
onChange: (value) => {
|
|
30564
|
+
if (value) {
|
|
30565
|
+
api?.setParagraphStyle(value === "__normal" ? null : value);
|
|
29542
30566
|
setCurStyle(api?.getParagraphStyleId?.() ?? null);
|
|
29543
30567
|
}
|
|
29544
|
-
}
|
|
29545
|
-
style: { ...selectStyle, width: 92 },
|
|
29546
|
-
children: [
|
|
29547
|
-
/* @__PURE__ */ jsx("option", { value: "__normal", children: "Normal" }),
|
|
29548
|
-
(api?.listParagraphStyles() ?? []).filter((s) => !/^normal$/i.test(s.name)).map((s) => /* @__PURE__ */ jsx("option", { value: s.id, children: s.name }, s.id)),
|
|
29549
|
-
curStyle !== null && !(api?.listParagraphStyles() ?? []).some((s) => s.id === curStyle) && /* @__PURE__ */ jsx("option", { value: curStyle, children: api?.document.styles.byId.get(curStyle)?.name ?? curStyle })
|
|
29550
|
-
]
|
|
30568
|
+
}
|
|
29551
30569
|
}
|
|
29552
30570
|
)
|
|
29553
30571
|
});
|
|
29554
30572
|
if (on("font"))
|
|
29555
30573
|
groups.push({
|
|
29556
30574
|
key: "font",
|
|
29557
|
-
node: /* @__PURE__ */
|
|
29558
|
-
|
|
30575
|
+
node: /* @__PURE__ */ jsx(
|
|
30576
|
+
ToolbarMenuSelect,
|
|
29559
30577
|
{
|
|
29560
30578
|
title: "Font",
|
|
29561
30579
|
value: fmt?.fontFamily ?? "",
|
|
29562
|
-
|
|
29563
|
-
|
|
29564
|
-
|
|
29565
|
-
|
|
29566
|
-
|
|
29567
|
-
|
|
29568
|
-
|
|
30580
|
+
placeholder: "Font",
|
|
30581
|
+
width: 130,
|
|
30582
|
+
menuWidth: 210,
|
|
30583
|
+
options: (fmt?.fontFamily && !detectFonts().includes(fmt.fontFamily) ? [fmt.fontFamily, ...detectFonts()] : detectFonts()).map((font) => ({
|
|
30584
|
+
value: font,
|
|
30585
|
+
label: font,
|
|
30586
|
+
fontFamily: font
|
|
30587
|
+
})),
|
|
30588
|
+
onChange: (value) => value && apply({ fontFamily: value })
|
|
29569
30589
|
}
|
|
29570
30590
|
)
|
|
29571
30591
|
});
|
|
@@ -29573,18 +30593,16 @@ function DocxToolbar({
|
|
|
29573
30593
|
groups.push({
|
|
29574
30594
|
key: "size",
|
|
29575
30595
|
node: /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
29576
|
-
/* @__PURE__ */
|
|
29577
|
-
|
|
30596
|
+
/* @__PURE__ */ jsx(
|
|
30597
|
+
ToolbarMenuSelect,
|
|
29578
30598
|
{
|
|
29579
30599
|
title: "Font size",
|
|
29580
|
-
value: fmt?.fontSizePt
|
|
29581
|
-
|
|
29582
|
-
|
|
29583
|
-
|
|
29584
|
-
|
|
29585
|
-
|
|
29586
|
-
SIZES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: s }, s))
|
|
29587
|
-
]
|
|
30600
|
+
value: fmt?.fontSizePt === void 0 ? "" : String(fmt.fontSizePt),
|
|
30601
|
+
placeholder: "Size",
|
|
30602
|
+
width: 58,
|
|
30603
|
+
menuWidth: 92,
|
|
30604
|
+
options: SIZES.map((size) => ({ value: String(size), label: String(size) })),
|
|
30605
|
+
onChange: (value) => value && apply({ fontSizePt: parseFloat(value) })
|
|
29588
30606
|
}
|
|
29589
30607
|
),
|
|
29590
30608
|
/* @__PURE__ */ jsx(Sep, {})
|
|
@@ -29641,19 +30659,15 @@ function DocxToolbar({
|
|
|
29641
30659
|
if (on("color"))
|
|
29642
30660
|
groups.push({
|
|
29643
30661
|
key: "color",
|
|
29644
|
-
node: /* @__PURE__ */
|
|
29645
|
-
|
|
29646
|
-
|
|
29647
|
-
"
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
|
|
29652
|
-
|
|
29653
|
-
style: { width: 0, height: 0, opacity: 0, border: "none", padding: 0 }
|
|
29654
|
-
}
|
|
29655
|
-
)
|
|
29656
|
-
] })
|
|
30662
|
+
node: /* @__PURE__ */ jsx(
|
|
30663
|
+
ColorMenu,
|
|
30664
|
+
{
|
|
30665
|
+
current: fmt?.color && fmt.color !== "auto" ? fmt.color : "#000000",
|
|
30666
|
+
title: "Text color",
|
|
30667
|
+
trigger: /* @__PURE__ */ jsx("span", { style: { fontSize: 13, borderBottom: `3px solid ${fmt?.color && fmt.color !== "auto" ? fmt.color : "#000"}`, padding: "0 3px", color: T.fg }, children: "A" }),
|
|
30668
|
+
onPick: (value) => apply({ color: value })
|
|
30669
|
+
}
|
|
30670
|
+
)
|
|
29657
30671
|
});
|
|
29658
30672
|
if (on("highlight"))
|
|
29659
30673
|
groups.push({
|
|
@@ -30325,19 +31339,23 @@ function DocxView({
|
|
|
30325
31339
|
"Calibri",
|
|
30326
31340
|
"Calibri Light",
|
|
30327
31341
|
"Tahoma",
|
|
30328
|
-
"Franklin Gothic Medium"
|
|
30329
|
-
// Complex-script faces gate layout too (advances must be real
|
|
30330
|
-
// before line breaking): Mangal (Devanagari), Latha (Tamil),
|
|
30331
|
-
// Noto Sans Lao Looped (Lao — bundled OFL webfont).
|
|
30332
|
-
"Mangal",
|
|
30333
|
-
"Latha",
|
|
30334
|
-
"Noto Sans Lao Looped"
|
|
31342
|
+
"Franklin Gothic Medium"
|
|
30335
31343
|
];
|
|
30336
31344
|
for (const fam of latin) {
|
|
30337
31345
|
for (const variant of ["", "italic ", "bold ", "bold italic "]) {
|
|
30338
31346
|
loads.push(document.fonts.load(`${variant}16px "${fam}"`).catch(() => []));
|
|
30339
31347
|
}
|
|
30340
31348
|
}
|
|
31349
|
+
const complex = [
|
|
31350
|
+
["Mangal", "\u0905"],
|
|
31351
|
+
["Latha", "\u0B85"],
|
|
31352
|
+
["Noto Sans Lao Looped", "\u0E81"]
|
|
31353
|
+
];
|
|
31354
|
+
for (const [fam, sample] of complex) {
|
|
31355
|
+
for (const variant of ["", "bold "]) {
|
|
31356
|
+
loads.push(document.fonts.load(`${variant}16px "${fam}"`, sample).catch(() => []));
|
|
31357
|
+
}
|
|
31358
|
+
}
|
|
30341
31359
|
loads.push(document.fonts.load('16px "Cambria Math"').catch(() => []));
|
|
30342
31360
|
const cjk = [
|
|
30343
31361
|
"MS Mincho",
|
|
@@ -30353,7 +31371,7 @@ function DocxView({
|
|
|
30353
31371
|
];
|
|
30354
31372
|
for (const fam of cjk) {
|
|
30355
31373
|
for (const variant of ["", "bold "]) {
|
|
30356
|
-
loads.push(document.fonts.load(`${variant}16px "${fam}"
|
|
31374
|
+
loads.push(document.fonts.load(`${variant}16px "${fam}"`, "A\u6F22").catch(() => []));
|
|
30357
31375
|
}
|
|
30358
31376
|
}
|
|
30359
31377
|
await Promise.all(loads);
|
|
@@ -30400,7 +31418,39 @@ function DocxView({
|
|
|
30400
31418
|
else if (formatted.length > 0) editor?.selectRanges(formatted);
|
|
30401
31419
|
document.dispatchEvent(new CustomEvent("dxw-selection"));
|
|
30402
31420
|
},
|
|
30403
|
-
onStyleShortcut: (styleId) => applyStyleShortcut?.(styleId)
|
|
31421
|
+
onStyleShortcut: (styleId) => applyStyleShortcut?.(styleId),
|
|
31422
|
+
onTextCommand: (command) => {
|
|
31423
|
+
const current = apiRef.current;
|
|
31424
|
+
if (!current) return;
|
|
31425
|
+
if (command === "link") {
|
|
31426
|
+
const anchor = containerRef.current;
|
|
31427
|
+
if (!anchor) return;
|
|
31428
|
+
void requestTextInputDialog(anchor, {
|
|
31429
|
+
title: "Link address",
|
|
31430
|
+
label: "URL",
|
|
31431
|
+
value: current.getLinkAt() ?? "https://"
|
|
31432
|
+
}).then((next) => {
|
|
31433
|
+
if (next !== null) current.setLink(next.trim() || null);
|
|
31434
|
+
});
|
|
31435
|
+
} else if (command === "comment") {
|
|
31436
|
+
const anchor = containerRef.current;
|
|
31437
|
+
if (!anchor) return;
|
|
31438
|
+
void requestTextInputDialog(anchor, {
|
|
31439
|
+
title: "New comment",
|
|
31440
|
+
label: "Comment",
|
|
31441
|
+
submitLabel: "Comment",
|
|
31442
|
+
multiline: true
|
|
31443
|
+
}).then((text) => {
|
|
31444
|
+
if (text?.trim()) current.addComment(text.trim());
|
|
31445
|
+
});
|
|
31446
|
+
} else if (command === "bullet" || command === "number") {
|
|
31447
|
+
current.toggleList(command);
|
|
31448
|
+
} else {
|
|
31449
|
+
current.setAlignment(
|
|
31450
|
+
command === "alignLeft" ? "left" : command === "alignCenter" ? "center" : command === "alignRight" ? "right" : "justify"
|
|
31451
|
+
);
|
|
31452
|
+
}
|
|
31453
|
+
}
|
|
30404
31454
|
};
|
|
30405
31455
|
editor = new DocxEditor(editorConfig);
|
|
30406
31456
|
editor.attach();
|
|
@@ -31019,7 +32069,8 @@ function DocxView({
|
|
|
31019
32069
|
alignItems: "center"
|
|
31020
32070
|
},
|
|
31021
32071
|
children: [
|
|
31022
|
-
/* @__PURE__ */ jsx2("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer" }),
|
|
32072
|
+
/* @__PURE__ */ jsx2("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer \xB7 repeats on pages" }),
|
|
32073
|
+
hotBtn("Line", "Insert a reusable line in the repeating page layer", () => apiRef.current?.insertShape("line")),
|
|
31023
32074
|
hotBtn("Page number", "Insert a dynamic page number at the caret", () => apiRef.current?.insertPageNumber("page")),
|
|
31024
32075
|
hotBtn("Page X of Y", "Insert 'Page X of Y' at the caret", () => apiRef.current?.insertPageNumber("pageOfTotal")),
|
|
31025
32076
|
hotBtn("Close", "Return to the document body", () => {
|
|
@@ -31035,6 +32086,7 @@ export {
|
|
|
31035
32086
|
DocxDocument,
|
|
31036
32087
|
DocxToolbar,
|
|
31037
32088
|
DocxView,
|
|
32089
|
+
ToolbarMenuSelect,
|
|
31038
32090
|
layoutDocument,
|
|
31039
32091
|
printPages,
|
|
31040
32092
|
renderToDom
|