@arbidocs/blocks 0.4.102 → 0.4.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/index.cjs +207 -207
- package/dist/agents/index.js +2 -2
- package/dist/{chunk-AOFATOT3.cjs → chunk-2A4MDHJR.cjs} +7 -5
- package/dist/chunk-2A4MDHJR.cjs.map +1 -0
- package/dist/{chunk-G5JH2YMQ.js → chunk-4GFB5U3K.js} +3 -3
- package/dist/{chunk-G5JH2YMQ.js.map → chunk-4GFB5U3K.js.map} +1 -1
- package/dist/chunk-5FYU7ZIU.cjs +139 -0
- package/dist/chunk-5FYU7ZIU.cjs.map +1 -0
- package/dist/{chunk-Y5XW57U4.cjs → chunk-7LLLQUM7.cjs} +5 -5
- package/dist/{chunk-Y5XW57U4.cjs.map → chunk-7LLLQUM7.cjs.map} +1 -1
- package/dist/{chunk-D3QPYKZG.js → chunk-EPHGD4YV.js} +7 -6
- package/dist/chunk-EPHGD4YV.js.map +1 -0
- package/dist/chunk-HFZ45FD3.js +133 -0
- package/dist/chunk-HFZ45FD3.js.map +1 -0
- package/dist/{chunk-5NQIBJPP.js → chunk-NJX774HB.js} +3 -3
- package/dist/{chunk-5NQIBJPP.js.map → chunk-NJX774HB.js.map} +1 -1
- package/dist/{chunk-DDYXFALG.cjs → chunk-NW3LFDZL.cjs} +3 -3
- package/dist/{chunk-DDYXFALG.cjs.map → chunk-NW3LFDZL.cjs.map} +1 -1
- package/dist/{chunk-YGREW5TZ.js → chunk-PIT2YZCK.js} +3 -3
- package/dist/{chunk-YGREW5TZ.js.map → chunk-PIT2YZCK.js.map} +1 -1
- package/dist/{chunk-Z3G65XHZ.js → chunk-S55VDTX3.js} +3 -3
- package/dist/{chunk-Z3G65XHZ.js.map → chunk-S55VDTX3.js.map} +1 -1
- package/dist/{chunk-LENXDIMY.cjs → chunk-SKSE4OT6.cjs} +22 -22
- package/dist/{chunk-LENXDIMY.cjs.map → chunk-SKSE4OT6.cjs.map} +1 -1
- package/dist/{chunk-ZT2EBBSC.cjs → chunk-TP3FAP5J.cjs} +5 -5
- package/dist/{chunk-ZT2EBBSC.cjs.map → chunk-TP3FAP5J.cjs.map} +1 -1
- package/dist/{chunk-MYALCKDR.js → chunk-W2RTZOK3.js} +1533 -263
- package/dist/chunk-W2RTZOK3.js.map +1 -0
- package/dist/{chunk-FAGQTB3D.cjs → chunk-ZWWN4CUL.cjs} +1690 -408
- package/dist/chunk-ZWWN4CUL.cjs.map +1 -0
- package/dist/connect/docx.cjs +8 -7
- package/dist/connect/docx.cjs.map +1 -1
- package/dist/connect/docx.js +6 -5
- package/dist/connect/docx.js.map +1 -1
- package/dist/connect/index.cjs +12 -11
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +5 -4
- package/dist/connect/index.js.map +1 -1
- package/dist/docx/LinkHoverCard.d.ts +24 -0
- package/dist/docx/NativeDocxEditor.d.ts +6 -0
- package/dist/docx/RibbonMenu.d.ts +4 -1
- package/dist/docx/RibbonOverflow.d.ts +27 -0
- package/dist/docx/WordReferences.d.ts +3 -2
- package/dist/docx/beforeSave.d.ts +9 -0
- package/dist/docx/definitions/fragment.d.ts +19 -1
- package/dist/docx/definitions/port.d.ts +43 -11
- package/dist/docx/index.cjs +85 -36
- package/dist/docx/index.cjs.map +1 -1
- package/dist/docx/index.d.ts +6 -0
- package/dist/docx/index.js +5 -4
- package/dist/docx/index.js.map +1 -1
- package/dist/docx/noteStyles.d.ts +46 -0
- package/dist/docx/overflowPlan.d.ts +15 -0
- package/dist/docx/references/CrossReferences.d.ts +97 -0
- package/dist/docx/references/EditorMenus.d.ts +10 -0
- package/dist/docx/references/commands.d.ts +119 -0
- package/dist/docx/references/numbering.d.ts +49 -0
- package/dist/docx/references/passages.d.ts +32 -0
- package/dist/docx/references/port.d.ts +20 -0
- package/dist/facts/index.cjs +22 -129
- package/dist/facts/index.cjs.map +1 -1
- package/dist/facts/index.js +3 -125
- package/dist/facts/index.js.map +1 -1
- package/dist/files/index.cjs +1 -1
- package/dist/files/index.js +1 -1
- package/dist/home/index.cjs +1 -1
- package/dist/home/index.js +1 -1
- package/dist/index.cjs +314 -314
- package/dist/index.js +8 -8
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/studio/index.cjs +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/tags/ooxml.d.ts +4 -0
- package/dist/workflow-canvas/index.cjs +9 -9
- package/dist/workflow-canvas/index.js +2 -2
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +4 -4
- package/src/docx/README.md +32 -0
- package/src/docx/styles.css +73 -5
- package/dist/chunk-AOFATOT3.cjs.map +0 -1
- package/dist/chunk-D3QPYKZG.js.map +0 -1
- package/dist/chunk-FAGQTB3D.cjs.map +0 -1
- package/dist/chunk-MYALCKDR.js.map +0 -1
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { FactPassageItem } from './chunk-HFZ45FD3.js';
|
|
3
|
+
import { stylesXml, definitionBookmark, groupDefinitions, definitionLabels, filterTermGroups, esc, hyperlinkRelationship, docxPackage, documentXml, definitionIdOfBookmark, compareTerms, parseDefinition } from './chunk-EPHGD4YV.js';
|
|
3
4
|
import { filterMentionCandidates, MentionMenu, findMentionQuery, listOptionId, extractMentions, useListKeyNav } from './chunk-AA3PT6KR.js';
|
|
4
5
|
import { unzipSync, strFromU8, strToU8, zipSync } from 'fflate';
|
|
5
6
|
import { collectReviewItems, revisionItemsOf } from '@docx-editor.dev/core/store';
|
|
6
|
-
import
|
|
7
|
+
import React4, { createContext, useContext, useState, useRef, useCallback, useEffect, useLayoutEffect, useMemo, useSyncExternalStore } from 'react';
|
|
7
8
|
import { useDocxEditor, ReviewRailContext, useEditorSnapshot, useEditorState, useChromeTranslate, DocxEditor, createFontSource, useParagraphStyle, normalizeImageBytes, usePageSetup, useEditorCommand } from '@docx-editor.dev/react';
|
|
8
|
-
import { AiMarkdown, Dialog, DialogContent, DialogHeader, DialogTitle, cn, splitMarkdownBlocks } from '@arbidocs/react/ui';
|
|
9
|
-
import { MessageSquarePlus, MessageSquare, PencilLine, ChevronLeft, ChevronRight, X, ChevronUp, ChevronDown, CheckCheck, RotateCcw, CircleCheck, Trash2, Check, SendHorizontal, Loader2, Sparkles, Type,
|
|
9
|
+
import { AiMarkdown, Dialog, DialogContent, DialogHeader, DialogTitle, cn, DialogDescription, Button, DialogFooter, Tabs, TabsList, TabsTrigger, TabsContent, Input, splitMarkdownBlocks } from '@arbidocs/react/ui';
|
|
10
|
+
import { MessageSquarePlus, MessageSquare, PencilLine, ChevronLeft, ChevronRight, X, ChevronUp, ChevronDown, CheckCheck, RotateCcw, CircleCheck, Trash2, Check, SendHorizontal, Loader2, Sparkles, Type, Pilcrow, UsersRound, RefreshCw, WifiOff, Download, Save, Ellipsis, BookA, Blocks, Link2, Superscript, NotebookText, RefreshCcw, Columns2, Settings2, BetweenHorizontalStart, BetweenHorizontalEnd, BetweenVerticalStart, BetweenVerticalEnd, Merge, Split, Heading, AlignVerticalJustifyStart, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, RotateCw, FlipHorizontal2, FlipVertical2, Scaling, RectangleVertical, RectangleHorizontal, FileText, SeparatorHorizontal, Captions } from 'lucide-react';
|
|
10
11
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
11
12
|
import { createPortal } from 'react-dom';
|
|
12
13
|
import { defaultLegalTemplate, listBuildingBlocks, attachedTemplateOf, linkedLevelStyles, styleDivergence, buildingBlockFragment, fragmentClipboardHtml, trackInsertion, newFromTemplate } from '@arbidocs/coedit/template';
|
|
14
|
+
import { resolveNumberingLevel, resolveStoryListItems, buildStyleCascadeTable, withNumberingStyleLinks, buildNumberingIndex } from '@docx-editor.dev/core/layout';
|
|
13
15
|
import { executeImageCommand } from '@docx-editor.dev/core/editor';
|
|
14
16
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
15
17
|
import * as Y from 'yjs';
|
|
@@ -896,7 +898,7 @@ function DocxCommentActivity() {
|
|
|
896
898
|
const thread = review.items.filter(
|
|
897
899
|
(entry) => entry.kind === "comment" && (entry.item.id === commentId || entry.parentId === commentId)
|
|
898
900
|
);
|
|
899
|
-
const statuses = Object.entries(activity).filter(([,
|
|
901
|
+
const statuses = Object.entries(activity).filter(([, run2]) => run2.commentId === commentId);
|
|
900
902
|
const labels = {
|
|
901
903
|
delivering: "Delivering mention\u2026",
|
|
902
904
|
queued: "Queued\u2026",
|
|
@@ -908,18 +910,18 @@ function DocxCommentActivity() {
|
|
|
908
910
|
unknown: "Status unavailable"
|
|
909
911
|
};
|
|
910
912
|
return /* @__PURE__ */ jsxs("div", { className: "native-docx-comment-extra", "data-review-selectable": "", children: [
|
|
911
|
-
statuses.map(([id,
|
|
913
|
+
statuses.map(([id, run2]) => /* @__PURE__ */ jsxs(
|
|
912
914
|
"div",
|
|
913
915
|
{
|
|
914
916
|
role: "status",
|
|
915
917
|
"data-testid": "docx-comment-agent-status",
|
|
916
|
-
"data-status":
|
|
918
|
+
"data-status": run2.status,
|
|
917
919
|
className: "native-docx-comment-activity",
|
|
918
920
|
children: [
|
|
919
|
-
["delivering", "queued", "in_progress"].includes(
|
|
920
|
-
|
|
921
|
+
["delivering", "queued", "in_progress"].includes(run2.status) && /* @__PURE__ */ jsx("span", { className: "native-docx-agent-spinner", "aria-hidden": "true" }),
|
|
922
|
+
run2.label,
|
|
921
923
|
": ",
|
|
922
|
-
labels[
|
|
924
|
+
labels[run2.status]
|
|
923
925
|
]
|
|
924
926
|
},
|
|
925
927
|
id
|
|
@@ -947,10 +949,10 @@ function DocxCommentActivity() {
|
|
|
947
949
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: entry.author || "Reviewer" }),
|
|
948
950
|
/* @__PURE__ */ jsx("div", { "data-testid": "docx-full-comment-text", children: /* @__PURE__ */ jsx(AiMarkdown, { allowHtml: false, children: commentText(entry) }) })
|
|
949
951
|
] }, entry.key)),
|
|
950
|
-
statuses.map(([id,
|
|
951
|
-
|
|
952
|
+
statuses.map(([id, run2]) => /* @__PURE__ */ jsxs("p", { role: "status", className: "text-sm", children: [
|
|
953
|
+
run2.label,
|
|
952
954
|
": ",
|
|
953
|
-
labels[
|
|
955
|
+
labels[run2.status]
|
|
954
956
|
] }, id))
|
|
955
957
|
]
|
|
956
958
|
}
|
|
@@ -1262,9 +1264,19 @@ function DocxMentions({
|
|
|
1262
1264
|
) });
|
|
1263
1265
|
}
|
|
1264
1266
|
var DEFINED_TERM_STYLE = "DefinedTerm";
|
|
1265
|
-
var
|
|
1267
|
+
var CROSS_REFERENCE_STYLE = "CrossReference";
|
|
1268
|
+
var BROKEN_CROSS_REFERENCE_STYLE = "CrossReferenceBroken";
|
|
1269
|
+
var CHARACTER_STYLES = {
|
|
1270
|
+
[DEFINED_TERM_STYLE]: `<w:style w:type="character" w:customStyle="1" w:styleId="${DEFINED_TERM_STYLE}"><w:name w:val="Defined Term"/><w:rPr><w:u w:val="dotted" w:color="7F7F7F"/></w:rPr></w:style>`,
|
|
1271
|
+
[CROSS_REFERENCE_STYLE]: `<w:style w:type="character" w:customStyle="1" w:styleId="${CROSS_REFERENCE_STYLE}"><w:name w:val="Cross Reference"/><w:rPr><w:color w:val="1F4E79"/><w:u w:val="dotted" w:color="8EA9C1"/></w:rPr></w:style>`,
|
|
1272
|
+
[BROKEN_CROSS_REFERENCE_STYLE]: `<w:style w:type="character" w:customStyle="1" w:styleId="${BROKEN_CROSS_REFERENCE_STYLE}"><w:name w:val="Cross Reference Broken"/><w:basedOn w:val="${CROSS_REFERENCE_STYLE}"/><w:rPr><w:color w:val="C00000"/><w:u w:val="wave" w:color="C00000"/></w:rPr></w:style>`
|
|
1273
|
+
};
|
|
1274
|
+
function stylesUsed(body) {
|
|
1275
|
+
return [...new Set([...body.matchAll(/<w:rStyle w:val="([^"]+)"/g)].map((m) => m[1]))];
|
|
1276
|
+
}
|
|
1277
|
+
var fragmentStyles = (ids) => stylesXml(
|
|
1266
1278
|
"",
|
|
1267
|
-
`<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style
|
|
1279
|
+
`<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style>${ids.map((id) => CHARACTER_STYLES[id] ?? "").join("")}`
|
|
1268
1280
|
);
|
|
1269
1281
|
var textRun = (text, props = "") => `<w:r>${props ? `<w:rPr>${props}</w:rPr>` : ""}<w:t xml:space="preserve">${esc(text)}</w:t></w:r>`;
|
|
1270
1282
|
function definitionTooltip(definition) {
|
|
@@ -1292,11 +1304,16 @@ function base64(bytes) {
|
|
|
1292
1304
|
binary += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
1293
1305
|
return btoa(binary);
|
|
1294
1306
|
}
|
|
1295
|
-
function fragmentHtml(body, covered2,
|
|
1307
|
+
function fragmentHtml(body, covered2, {
|
|
1308
|
+
revision,
|
|
1309
|
+
relationships,
|
|
1310
|
+
styles = stylesUsed(body)
|
|
1311
|
+
} = {}) {
|
|
1296
1312
|
const untracked = docxPackage({
|
|
1297
1313
|
document: documentXml(body),
|
|
1298
|
-
styles:
|
|
1299
|
-
title: "Defined terms"
|
|
1314
|
+
styles: fragmentStyles(styles),
|
|
1315
|
+
title: "Defined terms",
|
|
1316
|
+
relationships
|
|
1300
1317
|
});
|
|
1301
1318
|
const bytes = revision ? trackInsertion(untracked, revision, covered2) : untracked;
|
|
1302
1319
|
return `<div data-docx-fragment="${base64(bytes)}" data-docx-fragment-end="${covered2 ? "covered" : "open"}"></div>`;
|
|
@@ -1395,9 +1412,93 @@ function definitionOfAnchor(anchor, definitions) {
|
|
|
1395
1412
|
const id = definitionIdOfBookmark(anchor.replace(/^#/, ""));
|
|
1396
1413
|
return id ? definitions.get(id) : void 0;
|
|
1397
1414
|
}
|
|
1415
|
+
function LinkHoverCard({
|
|
1416
|
+
root,
|
|
1417
|
+
matches,
|
|
1418
|
+
resolve,
|
|
1419
|
+
onFirstHover,
|
|
1420
|
+
testId
|
|
1421
|
+
}) {
|
|
1422
|
+
const [card, setCard] = useState(null);
|
|
1423
|
+
const hovered = useRef(false);
|
|
1424
|
+
const latest = useRef({ matches, onFirstHover });
|
|
1425
|
+
latest.current = { matches, onFirstHover };
|
|
1426
|
+
useEffect(() => {
|
|
1427
|
+
if (!root) return;
|
|
1428
|
+
const over = (event) => {
|
|
1429
|
+
const link = event.target?.closest?.(
|
|
1430
|
+
"a.docx-hyperlink"
|
|
1431
|
+
);
|
|
1432
|
+
const href = link?.getAttribute("href") ?? "";
|
|
1433
|
+
if (!link || !href || !latest.current.matches(href, link)) return;
|
|
1434
|
+
if (!hovered.current) {
|
|
1435
|
+
hovered.current = true;
|
|
1436
|
+
latest.current.onFirstHover?.();
|
|
1437
|
+
}
|
|
1438
|
+
const title = link.getAttribute("title");
|
|
1439
|
+
if (title) {
|
|
1440
|
+
link.dataset.hoverTitle = title;
|
|
1441
|
+
link.removeAttribute("title");
|
|
1442
|
+
}
|
|
1443
|
+
const rect = link.getBoundingClientRect();
|
|
1444
|
+
setCard({
|
|
1445
|
+
left: rect.left,
|
|
1446
|
+
top: rect.bottom + 6,
|
|
1447
|
+
href,
|
|
1448
|
+
fallback: link.dataset.hoverTitle ?? ""
|
|
1449
|
+
});
|
|
1450
|
+
};
|
|
1451
|
+
const out = (event) => {
|
|
1452
|
+
const link = event.target?.closest?.("a.docx-hyperlink");
|
|
1453
|
+
if (link && !link.contains(event.relatedTarget)) setCard(null);
|
|
1454
|
+
};
|
|
1455
|
+
const hide = () => setCard(null);
|
|
1456
|
+
root.addEventListener("mouseover", over);
|
|
1457
|
+
root.addEventListener("mouseout", out);
|
|
1458
|
+
window.addEventListener("keydown", hide, true);
|
|
1459
|
+
window.addEventListener("pointerdown", hide, true);
|
|
1460
|
+
window.addEventListener("scroll", hide, true);
|
|
1461
|
+
return () => {
|
|
1462
|
+
root.removeEventListener("mouseover", over);
|
|
1463
|
+
root.removeEventListener("mouseout", out);
|
|
1464
|
+
window.removeEventListener("keydown", hide, true);
|
|
1465
|
+
window.removeEventListener("pointerdown", hide, true);
|
|
1466
|
+
window.removeEventListener("scroll", hide, true);
|
|
1467
|
+
};
|
|
1468
|
+
}, [root]);
|
|
1469
|
+
if (!card) return null;
|
|
1470
|
+
const content = resolve(card.href);
|
|
1471
|
+
if (!content && !card.fallback) return null;
|
|
1472
|
+
return createPortal(
|
|
1473
|
+
/* @__PURE__ */ jsx(
|
|
1474
|
+
"div",
|
|
1475
|
+
{
|
|
1476
|
+
role: "tooltip",
|
|
1477
|
+
className: "native-docx-link-card rounded-md border border-border bg-popover p-3 text-sm text-popover-foreground shadow-lg",
|
|
1478
|
+
style: {
|
|
1479
|
+
position: "fixed",
|
|
1480
|
+
left: Math.max(8, Math.min(card.left, window.innerWidth - 348)),
|
|
1481
|
+
top: card.top,
|
|
1482
|
+
width: 340,
|
|
1483
|
+
zIndex: 1e3,
|
|
1484
|
+
pointerEvents: "none"
|
|
1485
|
+
},
|
|
1486
|
+
"data-testid": testId,
|
|
1487
|
+
children: content ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1488
|
+
content.title && /* @__PURE__ */ jsx("p", { className: "font-medium", children: content.title }),
|
|
1489
|
+
/* @__PURE__ */ jsx("p", { className: content.title ? "mt-1 text-muted-foreground" : void 0, children: content.body }),
|
|
1490
|
+
content.footer && /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: content.footer })
|
|
1491
|
+
] }) : /* @__PURE__ */ jsx("p", { children: card.fallback })
|
|
1492
|
+
}
|
|
1493
|
+
),
|
|
1494
|
+
document.body
|
|
1495
|
+
);
|
|
1496
|
+
}
|
|
1398
1497
|
|
|
1399
1498
|
// src/docx/definitions/port.ts
|
|
1499
|
+
var WATCHED_STYLES = /* @__PURE__ */ new Set([BROKEN_CROSS_REFERENCE_STYLE]);
|
|
1400
1500
|
var attr = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
|
|
1501
|
+
var FIELD_ATOM = "\uFFFC";
|
|
1401
1502
|
var HEADING_STYLE = /^(heading|berschrift|titre|t[ií]tulo|titolo|kop)\s*\d/i;
|
|
1402
1503
|
function readParagraphs(root) {
|
|
1403
1504
|
const out = [];
|
|
@@ -1424,8 +1525,44 @@ function readParagraph(node, topLevel, bookmarks) {
|
|
|
1424
1525
|
const links = [];
|
|
1425
1526
|
let styleId;
|
|
1426
1527
|
let outline = false;
|
|
1528
|
+
let fieldDepth = 0;
|
|
1529
|
+
const marks = [];
|
|
1530
|
+
let runStyle;
|
|
1531
|
+
const fields = [];
|
|
1532
|
+
let current = null;
|
|
1533
|
+
const field = (c) => {
|
|
1534
|
+
const type = attr(c, "fldCharType");
|
|
1535
|
+
if (type === "begin") {
|
|
1536
|
+
if (fieldDepth === 0) {
|
|
1537
|
+
current = { offset: text.length, instruction: "", result: "", inResult: false };
|
|
1538
|
+
text += FIELD_ATOM;
|
|
1539
|
+
}
|
|
1540
|
+
fieldDepth++;
|
|
1541
|
+
} else if (type === "separate" && fieldDepth === 1 && current) current.inResult = true;
|
|
1542
|
+
else if (type === "end") {
|
|
1543
|
+
fieldDepth = Math.max(0, fieldDepth - 1);
|
|
1544
|
+
if (fieldDepth === 0 && current) {
|
|
1545
|
+
const { offset, instruction, result } = current;
|
|
1546
|
+
fields.push({ offset, instruction: instruction.trim(), result });
|
|
1547
|
+
current = null;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1427
1551
|
const walk = (n, link) => {
|
|
1428
1552
|
for (const c of n.children ?? []) {
|
|
1553
|
+
if (c.localName === "fldChar") {
|
|
1554
|
+
field(c);
|
|
1555
|
+
continue;
|
|
1556
|
+
}
|
|
1557
|
+
if (c.localName === "fldSimple") {
|
|
1558
|
+
if (fieldDepth === 0) text += FIELD_ATOM;
|
|
1559
|
+
continue;
|
|
1560
|
+
}
|
|
1561
|
+
if (c.localName === "instrText") {
|
|
1562
|
+
if (fieldDepth === 1 && current)
|
|
1563
|
+
current.instruction += (c.children ?? []).map((t) => t.value ?? "").join("");
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1429
1566
|
if (c.kind === "paragraphProperties" || c.localName === "pPr") {
|
|
1430
1567
|
for (const p of c.children ?? []) {
|
|
1431
1568
|
if (p.localName === "pStyle") styleId = attr(p, "val");
|
|
@@ -1434,6 +1571,14 @@ function readParagraph(node, topLevel, bookmarks) {
|
|
|
1434
1571
|
continue;
|
|
1435
1572
|
}
|
|
1436
1573
|
if (c.localName === "delText" || c.localName === "del" || c.localName === "rPr") continue;
|
|
1574
|
+
if (c.localName === "r") {
|
|
1575
|
+
const rStyle = c.children?.find((x) => x.localName === "rPr")?.children?.find((x) => x.localName === "rStyle");
|
|
1576
|
+
const watched = rStyle && attr(rStyle, "val");
|
|
1577
|
+
runStyle = watched && WATCHED_STYLES.has(watched) ? watched : void 0;
|
|
1578
|
+
walk(c, link);
|
|
1579
|
+
runStyle = void 0;
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1437
1582
|
if (c.localName === "bookmarkStart") {
|
|
1438
1583
|
const name = attr(c, "name");
|
|
1439
1584
|
if (name) bookmarks.push(name);
|
|
@@ -1447,11 +1592,22 @@ function readParagraph(node, topLevel, bookmarks) {
|
|
|
1447
1592
|
continue;
|
|
1448
1593
|
}
|
|
1449
1594
|
if (c.kind === "textValue") {
|
|
1595
|
+
if (fieldDepth > 0) {
|
|
1596
|
+
const open = current;
|
|
1597
|
+
if (fieldDepth === 1 && open?.inResult) open.result += c.value ?? "";
|
|
1598
|
+
continue;
|
|
1599
|
+
}
|
|
1600
|
+
if (runStyle && c.value) {
|
|
1601
|
+
const last = marks[marks.length - 1];
|
|
1602
|
+
if (last && last.styleId === runStyle && last.offset + last.text.length === text.length)
|
|
1603
|
+
last.text += c.value;
|
|
1604
|
+
else marks.push({ styleId: runStyle, offset: text.length, text: c.value });
|
|
1605
|
+
}
|
|
1450
1606
|
text += c.value ?? "";
|
|
1451
1607
|
if (link) link.text += c.value ?? "";
|
|
1452
1608
|
continue;
|
|
1453
1609
|
}
|
|
1454
|
-
if (c.localName === "tab") text += " ";
|
|
1610
|
+
if (c.localName === "tab" && fieldDepth === 0) text += " ";
|
|
1455
1611
|
walk(c, link);
|
|
1456
1612
|
}
|
|
1457
1613
|
};
|
|
@@ -1463,9 +1619,20 @@ function readParagraph(node, topLevel, bookmarks) {
|
|
|
1463
1619
|
styleId,
|
|
1464
1620
|
topLevel,
|
|
1465
1621
|
bookmarks,
|
|
1466
|
-
links
|
|
1622
|
+
links,
|
|
1623
|
+
...fields.length ? { fields } : {},
|
|
1624
|
+
...marks.length ? { marks } : {}
|
|
1467
1625
|
};
|
|
1468
1626
|
}
|
|
1627
|
+
function documentStyleIds(root) {
|
|
1628
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1629
|
+
for (const style of root?.children ?? [])
|
|
1630
|
+
if (style.localName === "style") {
|
|
1631
|
+
const id = attr(style, "styleId");
|
|
1632
|
+
if (id) ids.add(id);
|
|
1633
|
+
}
|
|
1634
|
+
return ids;
|
|
1635
|
+
}
|
|
1469
1636
|
function editorPort(editor, revision) {
|
|
1470
1637
|
const surface = () => {
|
|
1471
1638
|
const s = editor.surface;
|
|
@@ -1485,8 +1652,17 @@ function editorPort(editor, revision) {
|
|
|
1485
1652
|
surface().setSelection({ anchor: from, head: to });
|
|
1486
1653
|
surface().deleteSelection();
|
|
1487
1654
|
},
|
|
1488
|
-
paste: (body, text, covered2) =>
|
|
1489
|
-
|
|
1655
|
+
paste: (body, text, covered2, relationships) => {
|
|
1656
|
+
const defined = documentStyleIds(surface().session.stylesRoot());
|
|
1657
|
+
const styles = stylesUsed(body).filter((id) => !defined.has(id));
|
|
1658
|
+
return editor.exec({
|
|
1659
|
+
type: "paste",
|
|
1660
|
+
text,
|
|
1661
|
+
html: fragmentHtml(body, covered2, { revision, relationships, styles })
|
|
1662
|
+
}).ok;
|
|
1663
|
+
},
|
|
1664
|
+
splitParagraph: () => surface().splitParagraph(),
|
|
1665
|
+
typeText: (text) => surface().insertPlainText(text)
|
|
1490
1666
|
};
|
|
1491
1667
|
}
|
|
1492
1668
|
function withDirectEditing(editor, fn) {
|
|
@@ -1499,34 +1675,68 @@ function withDirectEditing(editor, fn) {
|
|
|
1499
1675
|
if (mode === "suggesting") editor.setEditingMode("suggesting");
|
|
1500
1676
|
}
|
|
1501
1677
|
}
|
|
1502
|
-
function holdCaret(editor,
|
|
1678
|
+
function holdCaret(editor, { settleMs = 600, maxMs = 2e3 } = {}) {
|
|
1503
1679
|
const surface = editor.surface;
|
|
1504
1680
|
const selection = surface?.state().selection;
|
|
1505
1681
|
if (!surface || !selection) return;
|
|
1506
|
-
const {
|
|
1507
|
-
const paraId = surface.session.paraIdOf(paragraphId);
|
|
1682
|
+
const { offset } = selection.head;
|
|
1683
|
+
const paraId = surface.session.paraIdOf(selection.head.paragraphId);
|
|
1508
1684
|
if (!paraId) return;
|
|
1685
|
+
let typed = "";
|
|
1509
1686
|
let done = false;
|
|
1687
|
+
let settle;
|
|
1510
1688
|
const stop = () => {
|
|
1511
1689
|
done = true;
|
|
1512
1690
|
offChange();
|
|
1513
|
-
|
|
1514
|
-
clearTimeout(
|
|
1691
|
+
clearTimeout(settle);
|
|
1692
|
+
clearTimeout(limit);
|
|
1693
|
+
window.removeEventListener("keydown", key, true);
|
|
1694
|
+
window.removeEventListener("pointerdown", click, true);
|
|
1515
1695
|
};
|
|
1516
|
-
const
|
|
1696
|
+
const finish = () => {
|
|
1517
1697
|
if (done) return;
|
|
1518
|
-
const now = surface.state().selection;
|
|
1519
|
-
const node = surface.session.nodeIdOf(paraId);
|
|
1520
|
-
if (!now || !node) return;
|
|
1521
|
-
if (now.head.offset !== offset || now.head.paragraphId !== paragraphId) return stop();
|
|
1522
|
-
if (node === paragraphId) return;
|
|
1523
1698
|
stop();
|
|
1699
|
+
const node = surface.session.nodeIdOf(paraId);
|
|
1700
|
+
if (!node) return;
|
|
1524
1701
|
const point = { paragraphId: node, offset };
|
|
1525
1702
|
surface.setSelection({ anchor: point, head: point });
|
|
1703
|
+
if (typed) surface.insertPlainText(typed);
|
|
1704
|
+
};
|
|
1705
|
+
const key = (event) => {
|
|
1706
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
1707
|
+
event.preventDefault();
|
|
1708
|
+
event.stopPropagation();
|
|
1709
|
+
typed += event.key;
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1712
|
+
finish();
|
|
1713
|
+
};
|
|
1714
|
+
const click = () => {
|
|
1715
|
+
if (typed) finish();
|
|
1716
|
+
else stop();
|
|
1717
|
+
};
|
|
1718
|
+
const quiet = () => {
|
|
1719
|
+
clearTimeout(settle);
|
|
1720
|
+
settle = setTimeout(finish, settleMs);
|
|
1526
1721
|
};
|
|
1527
|
-
const offChange = editor.on("change",
|
|
1528
|
-
|
|
1529
|
-
|
|
1722
|
+
const offChange = editor.on("change", quiet);
|
|
1723
|
+
window.addEventListener("keydown", key, true);
|
|
1724
|
+
window.addEventListener("pointerdown", click, true);
|
|
1725
|
+
settle = setTimeout(finish, settleMs);
|
|
1726
|
+
const limit = setTimeout(finish, maxMs);
|
|
1727
|
+
}
|
|
1728
|
+
function preservingCaret(editor, fn) {
|
|
1729
|
+
const surface = editor.surface;
|
|
1730
|
+
const before = surface?.state().selection?.head;
|
|
1731
|
+
const paraId = before && surface?.session.paraIdOf(before.paragraphId);
|
|
1732
|
+
const result = fn();
|
|
1733
|
+
const node = paraId && surface?.session.nodeIdOf(paraId);
|
|
1734
|
+
if (before && node) {
|
|
1735
|
+
const point = { paragraphId: node, offset: before.offset };
|
|
1736
|
+
surface.setSelection({ anchor: point, head: point });
|
|
1737
|
+
holdCaret(editor);
|
|
1738
|
+
}
|
|
1739
|
+
return result;
|
|
1530
1740
|
}
|
|
1531
1741
|
|
|
1532
1742
|
// src/docx/structural/trackedOrNoted.ts
|
|
@@ -1690,19 +1900,26 @@ function DefinedTermsProvider({
|
|
|
1690
1900
|
},
|
|
1691
1901
|
[notify]
|
|
1692
1902
|
);
|
|
1693
|
-
const
|
|
1903
|
+
const run2 = useCallback(
|
|
1694
1904
|
(fn) => editor ? attempt(() => withDirectEditing(editor, fn)) : void 0,
|
|
1695
1905
|
[editor, attempt]
|
|
1696
1906
|
);
|
|
1907
|
+
const typedTrigger = (port) => {
|
|
1908
|
+
if (picker?.mode !== "typing") return 0;
|
|
1909
|
+
const caret = port.caret();
|
|
1910
|
+
const paragraph = caret && port.paragraphs().find((p) => p.id === caret.paragraphId);
|
|
1911
|
+
const match = paragraph && TRIGGER_QUERY.exec(paragraph.text.slice(0, caret.offset));
|
|
1912
|
+
return match ? DEFINED_TERM_TRIGGER.length + match[1].length : 0;
|
|
1913
|
+
};
|
|
1697
1914
|
const pick = useCallback(
|
|
1698
1915
|
(row) => {
|
|
1699
1916
|
if (!editor || !picker || !row) return;
|
|
1700
1917
|
const port = editorPort(editor);
|
|
1701
|
-
const placed =
|
|
1918
|
+
const placed = run2(() => {
|
|
1702
1919
|
if (picker.mode === "search" && picker.caret) port.setCaret(picker.caret);
|
|
1703
1920
|
const caret = port.caret();
|
|
1704
1921
|
if (!caret) throw new Error("Place the cursor where the term should go.");
|
|
1705
|
-
const typed =
|
|
1922
|
+
const typed = typedTrigger(port);
|
|
1706
1923
|
if (typed) port.deleteRange({ ...caret, offset: Math.max(0, caret.offset - typed) }, caret);
|
|
1707
1924
|
return true;
|
|
1708
1925
|
});
|
|
@@ -1718,7 +1935,7 @@ function DefinedTermsProvider({
|
|
|
1718
1935
|
if (result?.addedDefinition)
|
|
1719
1936
|
notify?.(`\u201C${row.definition.term}\u201D added to the Definitions section.`, "success");
|
|
1720
1937
|
},
|
|
1721
|
-
[editor, picker,
|
|
1938
|
+
[editor, picker, run2, attempt, track, notify]
|
|
1722
1939
|
);
|
|
1723
1940
|
const openPicker = useCallback(
|
|
1724
1941
|
(anchor) => {
|
|
@@ -1797,11 +2014,16 @@ function DefinedTermsProvider({
|
|
|
1797
2014
|
/* @__PURE__ */ jsx("span", { ref: marker, hidden: true }),
|
|
1798
2015
|
children,
|
|
1799
2016
|
load && /* @__PURE__ */ jsx(
|
|
1800
|
-
|
|
2017
|
+
LinkHoverCard,
|
|
1801
2018
|
{
|
|
1802
2019
|
root: viewer,
|
|
1803
|
-
|
|
1804
|
-
|
|
2020
|
+
matches: (href) => href.startsWith("#_dt_"),
|
|
2021
|
+
resolve: (href) => {
|
|
2022
|
+
const definition = definitionOfAnchor(href, byId);
|
|
2023
|
+
return definition ? { title: definition.term, body: definition.meaning, footer: sourceOf(definition) } : null;
|
|
2024
|
+
},
|
|
2025
|
+
onFirstHover: firstHover,
|
|
2026
|
+
testId: "docx-defined-term-card"
|
|
1805
2027
|
}
|
|
1806
2028
|
),
|
|
1807
2029
|
picker && createPortal(
|
|
@@ -1843,7 +2065,7 @@ function DefinedTermMenu({
|
|
|
1843
2065
|
onClose,
|
|
1844
2066
|
labels: l
|
|
1845
2067
|
}) {
|
|
1846
|
-
const listboxId =
|
|
2068
|
+
const listboxId = React4.useId();
|
|
1847
2069
|
const element = useRef(null);
|
|
1848
2070
|
const search = picker.mode === "search";
|
|
1849
2071
|
useEffect(() => {
|
|
@@ -1954,83 +2176,6 @@ function DefinedTermMenu({
|
|
|
1954
2176
|
}
|
|
1955
2177
|
);
|
|
1956
2178
|
}
|
|
1957
|
-
function DefinedTermHover({
|
|
1958
|
-
root,
|
|
1959
|
-
resolve,
|
|
1960
|
-
onFirstHover
|
|
1961
|
-
}) {
|
|
1962
|
-
const [card, setCard] = useState(null);
|
|
1963
|
-
const hovered = useRef(false);
|
|
1964
|
-
useEffect(() => {
|
|
1965
|
-
if (!root) return;
|
|
1966
|
-
const over = (event) => {
|
|
1967
|
-
const link = event.target?.closest?.(
|
|
1968
|
-
'a.docx-hyperlink[data-docx-link-kind="internal"]'
|
|
1969
|
-
);
|
|
1970
|
-
const href = link?.getAttribute("href") ?? "";
|
|
1971
|
-
if (!link || !href.startsWith("#_dt_")) return;
|
|
1972
|
-
if (!hovered.current) {
|
|
1973
|
-
hovered.current = true;
|
|
1974
|
-
onFirstHover();
|
|
1975
|
-
}
|
|
1976
|
-
const title = link.getAttribute("title");
|
|
1977
|
-
if (title) {
|
|
1978
|
-
link.dataset.definition = title;
|
|
1979
|
-
link.removeAttribute("title");
|
|
1980
|
-
}
|
|
1981
|
-
const rect = link.getBoundingClientRect();
|
|
1982
|
-
setCard({
|
|
1983
|
-
left: rect.left,
|
|
1984
|
-
top: rect.bottom + 6,
|
|
1985
|
-
anchor: href.slice(1),
|
|
1986
|
-
fallback: link.dataset.definition ?? ""
|
|
1987
|
-
});
|
|
1988
|
-
};
|
|
1989
|
-
const out = (event) => {
|
|
1990
|
-
const link = event.target?.closest?.("a.docx-hyperlink");
|
|
1991
|
-
if (link && !link.contains(event.relatedTarget)) setCard(null);
|
|
1992
|
-
};
|
|
1993
|
-
root.addEventListener("mouseover", over);
|
|
1994
|
-
root.addEventListener("mouseout", out);
|
|
1995
|
-
const hide = () => setCard(null);
|
|
1996
|
-
window.addEventListener("keydown", hide, true);
|
|
1997
|
-
window.addEventListener("pointerdown", hide, true);
|
|
1998
|
-
window.addEventListener("scroll", hide, true);
|
|
1999
|
-
return () => {
|
|
2000
|
-
root.removeEventListener("mouseover", over);
|
|
2001
|
-
root.removeEventListener("mouseout", out);
|
|
2002
|
-
window.removeEventListener("keydown", hide, true);
|
|
2003
|
-
window.removeEventListener("pointerdown", hide, true);
|
|
2004
|
-
window.removeEventListener("scroll", hide, true);
|
|
2005
|
-
};
|
|
2006
|
-
}, [root, onFirstHover]);
|
|
2007
|
-
if (!card) return null;
|
|
2008
|
-
const definition = resolve(card.anchor);
|
|
2009
|
-
return createPortal(
|
|
2010
|
-
/* @__PURE__ */ jsx(
|
|
2011
|
-
"div",
|
|
2012
|
-
{
|
|
2013
|
-
role: "tooltip",
|
|
2014
|
-
className: "native-docx-term-card rounded-md border border-border bg-popover p-3 text-sm text-popover-foreground shadow-lg",
|
|
2015
|
-
style: {
|
|
2016
|
-
position: "fixed",
|
|
2017
|
-
left: Math.max(8, Math.min(card.left, window.innerWidth - 348)),
|
|
2018
|
-
top: card.top,
|
|
2019
|
-
width: 340,
|
|
2020
|
-
zIndex: 1e3,
|
|
2021
|
-
pointerEvents: "none"
|
|
2022
|
-
},
|
|
2023
|
-
"data-testid": "docx-defined-term-card",
|
|
2024
|
-
children: definition ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2025
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium", children: definition.term }),
|
|
2026
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-muted-foreground", children: definition.meaning }),
|
|
2027
|
-
sourceOf(definition) && /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: sourceOf(definition) })
|
|
2028
|
-
] }) : /* @__PURE__ */ jsx("p", { children: card.fallback })
|
|
2029
|
-
}
|
|
2030
|
-
),
|
|
2031
|
-
document.body
|
|
2032
|
-
);
|
|
2033
|
-
}
|
|
2034
2179
|
var BUILTIN_TEMPLATE_NAME = "ARBI legal template";
|
|
2035
2180
|
var templateFileName = (t) => /\.(dotx|dotm|docx|docm)$/i.test(t.name) ? t.name : `${t.name}.dotx`;
|
|
2036
2181
|
var builtin;
|
|
@@ -2163,13 +2308,834 @@ function HouseTemplateProvider({
|
|
|
2163
2308
|
);
|
|
2164
2309
|
return /* @__PURE__ */ jsx(HouseTemplateContext.Provider, { value: enabled ? value : null, children });
|
|
2165
2310
|
}
|
|
2311
|
+
|
|
2312
|
+
// src/docx/references/numbering.ts
|
|
2313
|
+
var numbers = (level) => !!level && level.numFmt !== "bullet" && level.numFmt !== "none" && (level.lvlText ?? level.markerText ?? "").length > 0;
|
|
2314
|
+
function paragraphNumber(order, items, levelOf, paragraphId) {
|
|
2315
|
+
const item = items.get(paragraphId);
|
|
2316
|
+
if (!item || !numbers(item)) return null;
|
|
2317
|
+
const at = order.indexOf(paragraphId);
|
|
2318
|
+
const markerAt = (ilvl) => {
|
|
2319
|
+
if (ilvl === item.ilvl) return item.markerText;
|
|
2320
|
+
for (let i = at - 1; i >= 0; i--) {
|
|
2321
|
+
const other = items.get(order[i]);
|
|
2322
|
+
if (other && other.numId === item.numId && other.ilvl === ilvl) return other.markerText;
|
|
2323
|
+
}
|
|
2324
|
+
return null;
|
|
2325
|
+
};
|
|
2326
|
+
const chain = [];
|
|
2327
|
+
const texts = [];
|
|
2328
|
+
for (let u = item.ilvl; u >= 0; u--) {
|
|
2329
|
+
const level = levelOf(item.numId, u);
|
|
2330
|
+
if (!level || !numbers(level)) continue;
|
|
2331
|
+
if (u !== item.ilvl && texts.some((t) => t.includes(`%${u + 1}`))) continue;
|
|
2332
|
+
chain.push(u);
|
|
2333
|
+
texts.push(level.lvlText);
|
|
2334
|
+
}
|
|
2335
|
+
const value = chain.reverse().map((u) => markerAt(u) ?? "").join("");
|
|
2336
|
+
if (!value) return null;
|
|
2337
|
+
return value.length > 1 && value.endsWith(".") ? value.slice(0, -1) : value;
|
|
2338
|
+
}
|
|
2339
|
+
function listTargets(paragraphs, items, levelOf) {
|
|
2340
|
+
const order = paragraphs.map((p) => p.id);
|
|
2341
|
+
const out = [];
|
|
2342
|
+
for (const p of paragraphs) {
|
|
2343
|
+
const text = p.text.replace(//g, "").trim();
|
|
2344
|
+
if (!text) continue;
|
|
2345
|
+
const number = paragraphNumber(order, items, levelOf, p.id);
|
|
2346
|
+
const item = items.get(p.id);
|
|
2347
|
+
if (number !== null)
|
|
2348
|
+
out.push({
|
|
2349
|
+
paragraphId: p.id,
|
|
2350
|
+
kind: "numbered",
|
|
2351
|
+
number,
|
|
2352
|
+
marker: item?.markerText ?? "",
|
|
2353
|
+
text,
|
|
2354
|
+
heading: p.heading,
|
|
2355
|
+
level: item?.ilvl ?? 0
|
|
2356
|
+
});
|
|
2357
|
+
else if (p.heading)
|
|
2358
|
+
out.push({
|
|
2359
|
+
paragraphId: p.id,
|
|
2360
|
+
kind: "heading",
|
|
2361
|
+
number: null,
|
|
2362
|
+
marker: "",
|
|
2363
|
+
text,
|
|
2364
|
+
heading: true,
|
|
2365
|
+
level: 0
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2368
|
+
return out;
|
|
2369
|
+
}
|
|
2370
|
+
function filterTargets(targets, query) {
|
|
2371
|
+
const q = query.trim().toLowerCase();
|
|
2372
|
+
if (!q) return [...targets];
|
|
2373
|
+
return targets.filter(
|
|
2374
|
+
(t) => (t.number ?? "").toLowerCase().startsWith(q) || t.text.toLowerCase().includes(q)
|
|
2375
|
+
);
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
// src/docx/references/commands.ts
|
|
2379
|
+
var REF_BOOKMARK_PREFIX = "_Ref";
|
|
2380
|
+
function newRefBookmark(taken, random = Math.random) {
|
|
2381
|
+
for (; ; ) {
|
|
2382
|
+
const name = `${REF_BOOKMARK_PREFIX}${String(Math.floor(random() * 9e8) + 1e8)}`;
|
|
2383
|
+
if (!taken.has(name)) return name;
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
var styled = (style) => style ? `<w:rPr><w:rStyle w:val="${style}"/></w:rPr>` : "";
|
|
2387
|
+
var run = (text, style) => `<w:r>${styled(style)}<w:t xml:space="preserve">${esc(text)}</w:t></w:r>`;
|
|
2388
|
+
function refFieldXml(instruction, cached) {
|
|
2389
|
+
const r = (inner) => `<w:r>${styled(CROSS_REFERENCE_STYLE)}${inner}</w:r>`;
|
|
2390
|
+
return `${r('<w:fldChar w:fldCharType="begin"/>')}${r(
|
|
2391
|
+
`<w:instrText xml:space="preserve"> ${esc(instruction)} </w:instrText>`
|
|
2392
|
+
)}${r('<w:fldChar w:fldCharType="separate"/>')}${run(cached, CROSS_REFERENCE_STYLE)}${r(
|
|
2393
|
+
'<w:fldChar w:fldCharType="end"/>'
|
|
2394
|
+
)}`;
|
|
2395
|
+
}
|
|
2396
|
+
var refTooltip = (value, mode) => mode === "number" ? `Cross-reference to clause ${value}` : `Cross-reference to \u201C${value}\u201D`;
|
|
2397
|
+
function crossReferenceXml(bookmark, mode, value) {
|
|
2398
|
+
return `<w:hyperlink w:anchor="${esc(bookmark)}" w:tooltip="${esc(
|
|
2399
|
+
refTooltip(value, mode)
|
|
2400
|
+
)}" w:history="1">${refFieldXml(refInstruction(bookmark, mode), value)}</w:hyperlink>`;
|
|
2401
|
+
}
|
|
2402
|
+
var refInstruction = (bookmark, mode) => mode === "number" ? `REF ${bookmark} \\r \\h` : `REF ${bookmark} \\h`;
|
|
2403
|
+
var refResult = (target, mode) => mode === "number" && target.number ? target.number : target.text;
|
|
2404
|
+
var allBookmarks = (port) => new Set(port.paragraphs().flatMap((p) => p.bookmarks));
|
|
2405
|
+
function ensureTargetBookmark(port, target, mode) {
|
|
2406
|
+
const paragraph = port.paragraphs().find((p) => p.id === target.paragraphId);
|
|
2407
|
+
if (!paragraph) throw new Error("That clause is no longer in the document.");
|
|
2408
|
+
const existing = paragraph.bookmarks.find((b) => b.startsWith(REF_BOOKMARK_PREFIX));
|
|
2409
|
+
if (existing && mode === "number") return existing;
|
|
2410
|
+
const name = newRefBookmark(allBookmarks(port));
|
|
2411
|
+
const start = `<w:bookmarkStart w:id="0" w:name="${name}"/>`;
|
|
2412
|
+
const end = '<w:bookmarkEnd w:id="0"/>';
|
|
2413
|
+
if (mode === "number") {
|
|
2414
|
+
port.setCaret({ paragraphId: paragraph.id, offset: 0 });
|
|
2415
|
+
if (!port.paste(`<w:p>${start}${end}</w:p>`, "", false))
|
|
2416
|
+
throw new Error("The cross-reference target could not be marked.");
|
|
2417
|
+
return name;
|
|
2418
|
+
}
|
|
2419
|
+
const runs = port.runsXml(paragraph.id);
|
|
2420
|
+
if (!runs) throw new Error("This heading cannot be referred to by its text; use its number.");
|
|
2421
|
+
port.deleteRange(
|
|
2422
|
+
{ paragraphId: paragraph.id, offset: 0 },
|
|
2423
|
+
{ paragraphId: paragraph.id, offset: paragraph.text.length }
|
|
2424
|
+
);
|
|
2425
|
+
if (!port.paste(`<w:p>${start}${runs}${end}</w:p>`, paragraph.text, false))
|
|
2426
|
+
throw new Error("The cross-reference target could not be marked.");
|
|
2427
|
+
return name;
|
|
2428
|
+
}
|
|
2429
|
+
function pastePoint(port, caret) {
|
|
2430
|
+
const paragraph = port.paragraphs().find((p) => p.id === caret.paragraphId);
|
|
2431
|
+
if (paragraph?.text[caret.offset - 1] !== FIELD_ATOM) return caret;
|
|
2432
|
+
port.setCaret(caret);
|
|
2433
|
+
port.typeText(" ");
|
|
2434
|
+
return { paragraphId: caret.paragraphId, offset: caret.offset + 1 };
|
|
2435
|
+
}
|
|
2436
|
+
function markCrossReferenceTarget(port, target, mode) {
|
|
2437
|
+
if (mode === "number" && !target.number) mode = "text";
|
|
2438
|
+
const bookmark = ensureTargetBookmark(port, target, mode);
|
|
2439
|
+
return { bookmark, mode, value: refResult(target, mode) };
|
|
2440
|
+
}
|
|
2441
|
+
function insertCrossReferenceField(port, { bookmark, mode, value }, caret) {
|
|
2442
|
+
caret = pastePoint(port, caret);
|
|
2443
|
+
port.setCaret(caret);
|
|
2444
|
+
if (!port.paste(`<w:p>${crossReferenceXml(bookmark, mode, value)}</w:p>`, value, false))
|
|
2445
|
+
throw new Error("The cross-reference could not be inserted.");
|
|
2446
|
+
port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + 1 });
|
|
2447
|
+
return { bookmark };
|
|
2448
|
+
}
|
|
2449
|
+
function insertCrossReference(port, target, mode, caret) {
|
|
2450
|
+
return insertCrossReferenceField(port, markCrossReferenceTarget(port, target, mode), caret);
|
|
2451
|
+
}
|
|
2452
|
+
var documentReferenceTooltip = (text, appName = "ARBI") => `Cross-reference: ${text} \u2014 opens in ${appName}`;
|
|
2453
|
+
function insertDocumentReference(port, reference, caret) {
|
|
2454
|
+
const text = reference.text.trim();
|
|
2455
|
+
if (!text) throw new Error("Enter the reference text.");
|
|
2456
|
+
const tooltip = documentReferenceTooltip(text, reference.appName).slice(0, 255);
|
|
2457
|
+
caret = pastePoint(port, caret);
|
|
2458
|
+
port.setCaret(caret);
|
|
2459
|
+
const link = `<w:p><w:hyperlink r:id="rIdRef1"${tooltip ? ` w:tooltip="${esc(tooltip)}"` : ""} w:history="1">${run(text, CROSS_REFERENCE_STYLE)}</w:hyperlink></w:p>`;
|
|
2460
|
+
if (!port.paste(link, text, false, hyperlinkRelationship("rIdRef1", reference.url)))
|
|
2461
|
+
throw new Error("The reference could not be inserted.");
|
|
2462
|
+
port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + text.length });
|
|
2463
|
+
}
|
|
2464
|
+
var REF_FIELD = /^REF\s+(\S+)((?:\s+\\[A-Za-z*]+(?:\s+MERGEFORMAT)?)*)\s*$/i;
|
|
2465
|
+
function staleCrossReferences(port) {
|
|
2466
|
+
const paragraphs = port.paragraphs();
|
|
2467
|
+
if (!paragraphs.some((p) => p.fields?.length)) return [];
|
|
2468
|
+
const items = port.listItems();
|
|
2469
|
+
const order = paragraphs.map((p) => p.id);
|
|
2470
|
+
const owner = /* @__PURE__ */ new Map();
|
|
2471
|
+
for (const p of paragraphs) for (const b of p.bookmarks) if (!owner.has(b)) owner.set(b, p.id);
|
|
2472
|
+
const out = [];
|
|
2473
|
+
for (const p of paragraphs)
|
|
2474
|
+
for (const field of p.fields ?? []) {
|
|
2475
|
+
const match = REF_FIELD.exec(field.instruction);
|
|
2476
|
+
if (!match || !match[1].startsWith(REF_BOOKMARK_PREFIX)) continue;
|
|
2477
|
+
const switches = match[2].toLowerCase();
|
|
2478
|
+
const mode = /\\[rwn]\b/.test(switches) ? "number" : "text";
|
|
2479
|
+
const target = owner.get(match[1]);
|
|
2480
|
+
const base = {
|
|
2481
|
+
paragraphId: p.id,
|
|
2482
|
+
offset: field.offset,
|
|
2483
|
+
instruction: field.instruction,
|
|
2484
|
+
cached: field.result,
|
|
2485
|
+
bookmark: match[1],
|
|
2486
|
+
mode
|
|
2487
|
+
};
|
|
2488
|
+
if (!target) {
|
|
2489
|
+
out.push({ ...base, value: null });
|
|
2490
|
+
continue;
|
|
2491
|
+
}
|
|
2492
|
+
const value = /\\[rwn]\b/.test(switches) ? switches.includes("\\r") ? paragraphNumber(order, items, port.levelOf, target) : null : (paragraphs.find((x) => x.id === target)?.text ?? "").replace(//g, "").trim();
|
|
2493
|
+
if (value && value !== field.result.trim()) out.push({ ...base, value });
|
|
2494
|
+
}
|
|
2495
|
+
return out;
|
|
2496
|
+
}
|
|
2497
|
+
function brokenCrossReferences(port) {
|
|
2498
|
+
return port.paragraphs().flatMap(
|
|
2499
|
+
(p) => (p.marks ?? []).filter((m) => m.styleId === BROKEN_CROSS_REFERENCE_STYLE).map((m) => ({ paragraphId: p.id, offset: m.offset, text: m.text }))
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
function refreshCrossReferences(port) {
|
|
2503
|
+
const stale = staleCrossReferences(port).sort(
|
|
2504
|
+
(a, b) => a.paragraphId === b.paragraphId ? b.offset - a.offset : 0
|
|
2505
|
+
);
|
|
2506
|
+
let refreshed = 0;
|
|
2507
|
+
for (const ref of stale) {
|
|
2508
|
+
const paragraph = port.paragraphs().find((p) => p.id === ref.paragraphId);
|
|
2509
|
+
if (!paragraph || paragraph.text[ref.offset - 1] === FIELD_ATOM) continue;
|
|
2510
|
+
const at = { paragraphId: ref.paragraphId, offset: ref.offset };
|
|
2511
|
+
port.deleteRange(at, { paragraphId: ref.paragraphId, offset: ref.offset + 1 });
|
|
2512
|
+
port.setCaret(at);
|
|
2513
|
+
const text = ref.value ?? (ref.cached.trim() || ref.bookmark);
|
|
2514
|
+
const body = ref.value === null ? run(text, BROKEN_CROSS_REFERENCE_STYLE) : crossReferenceXml(ref.bookmark, ref.mode, ref.value);
|
|
2515
|
+
if (port.paste(`<w:p>${body}</w:p>`, text, false) && ref.value !== null) refreshed++;
|
|
2516
|
+
}
|
|
2517
|
+
return { refreshed, broken: brokenCrossReferences(port) };
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
// src/docx/references/passages.ts
|
|
2521
|
+
function shortTitle(title) {
|
|
2522
|
+
const base = title.replace(/\.[A-Za-z0-9]{1,5}$/, "").trim();
|
|
2523
|
+
const defined = /\(\s*(?:the\s+)?["“'‘]([^"”'’]{1,30})["”'’]\s*\)/i.exec(base);
|
|
2524
|
+
return defined ? defined[1] : base;
|
|
2525
|
+
}
|
|
2526
|
+
function passageClause(text) {
|
|
2527
|
+
const first = text.trim().split("\n")[0] ?? "";
|
|
2528
|
+
const match = /^(?:#+\s*)?(?:\*\*)?(?:clause|section|article)?\s*(\d+(?:\.\d+)*)[.)]?(?:\*\*)?\s+\S/i.exec(
|
|
2529
|
+
first
|
|
2530
|
+
);
|
|
2531
|
+
return match ? match[1] : null;
|
|
2532
|
+
}
|
|
2533
|
+
function referenceText(title, passage) {
|
|
2534
|
+
const name = shortTitle(title);
|
|
2535
|
+
const clause = passageClause(passage.text);
|
|
2536
|
+
if (clause) return `${name}, clause ${clause}`;
|
|
2537
|
+
if (passage.page) return `${name}, p. ${passage.page}`;
|
|
2538
|
+
return name;
|
|
2539
|
+
}
|
|
2540
|
+
function passageExcerpt(text, max = 280) {
|
|
2541
|
+
const plain = text.replace(/[#*_`>|]+/g, " ").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\s+/g, " ").trim();
|
|
2542
|
+
return plain.length > max ? `${plain.slice(0, max - 1)}\u2026` : plain;
|
|
2543
|
+
}
|
|
2544
|
+
function filterPassages(passages, query) {
|
|
2545
|
+
const q = query.trim().toLowerCase();
|
|
2546
|
+
return q ? passages.filter((p) => p.text.toLowerCase().includes(q)) : [...passages];
|
|
2547
|
+
}
|
|
2548
|
+
var RUN_PARTS = /* @__PURE__ */ new Set(["rPr", "t", "tab", "br", "lastRenderedPageBreak"]);
|
|
2549
|
+
var SKIPPED = /* @__PURE__ */ new Set(["pPr", "bookmarkStart", "bookmarkEnd", "proofErr", "permStart", "permEnd"]);
|
|
2550
|
+
function serialize(node) {
|
|
2551
|
+
if (node.kind === "textValue") return esc(node.value ?? "");
|
|
2552
|
+
const name = `${node.prefix ?? "w"}:${node.localName}`;
|
|
2553
|
+
const attrs = (node.attributes ?? []).map((a) => ` ${a.prefix ? `${a.prefix}:` : ""}${a.localName}="${esc(a.value)}"`).join("");
|
|
2554
|
+
const children = (node.children ?? []).map((c) => serialize(c)).join("");
|
|
2555
|
+
return children ? `<${name}${attrs}>${children}</${name}>` : `<${name}${attrs}/>`;
|
|
2556
|
+
}
|
|
2557
|
+
function paragraphRunsXml(paragraph) {
|
|
2558
|
+
const runs = [];
|
|
2559
|
+
for (const child of paragraph.children ?? []) {
|
|
2560
|
+
if (child.localName && SKIPPED.has(child.localName)) continue;
|
|
2561
|
+
if (child.localName !== "r") return null;
|
|
2562
|
+
if ((child.children ?? []).some((c) => !c.localName || !RUN_PARTS.has(c.localName))) return null;
|
|
2563
|
+
runs.push(serialize(child));
|
|
2564
|
+
}
|
|
2565
|
+
return runs.length ? runs.join("") : null;
|
|
2566
|
+
}
|
|
2567
|
+
function findNode2(node, id) {
|
|
2568
|
+
if (node.id === id) return node;
|
|
2569
|
+
for (const child of node.children ?? []) {
|
|
2570
|
+
const found = findNode2(child, id);
|
|
2571
|
+
if (found) return found;
|
|
2572
|
+
}
|
|
2573
|
+
return void 0;
|
|
2574
|
+
}
|
|
2575
|
+
function referencesPort(editor, revision) {
|
|
2576
|
+
const base = editorPort(editor, revision);
|
|
2577
|
+
const session = () => {
|
|
2578
|
+
const s = editor.surface?.session;
|
|
2579
|
+
if (!s) throw new Error("The document is not open.");
|
|
2580
|
+
return s;
|
|
2581
|
+
};
|
|
2582
|
+
const root = () => session().part().root;
|
|
2583
|
+
let numbering;
|
|
2584
|
+
let cascade;
|
|
2585
|
+
const index = () => {
|
|
2586
|
+
if (!numbering) {
|
|
2587
|
+
const s = session();
|
|
2588
|
+
cascade = buildStyleCascadeTable(s.stylesRoot(), void 0, s.settingsRoot());
|
|
2589
|
+
numbering = withNumberingStyleLinks(buildNumberingIndex(s.numberingRoot()), cascade);
|
|
2590
|
+
}
|
|
2591
|
+
return numbering;
|
|
2592
|
+
};
|
|
2593
|
+
return {
|
|
2594
|
+
...base,
|
|
2595
|
+
listItems: () => {
|
|
2596
|
+
const body = root().children?.find((n) => n.kind === "body");
|
|
2597
|
+
const items = resolveStoryListItems(
|
|
2598
|
+
body?.children ?? [],
|
|
2599
|
+
index(),
|
|
2600
|
+
cascade
|
|
2601
|
+
);
|
|
2602
|
+
const out = /* @__PURE__ */ new Map();
|
|
2603
|
+
for (const [id, item] of items)
|
|
2604
|
+
out.set(id, {
|
|
2605
|
+
numId: item.numId,
|
|
2606
|
+
ilvl: item.ilvl,
|
|
2607
|
+
markerText: item.markerText,
|
|
2608
|
+
numFmt: item.numFmt
|
|
2609
|
+
});
|
|
2610
|
+
return out;
|
|
2611
|
+
},
|
|
2612
|
+
levelOf: (numId, ilvl) => {
|
|
2613
|
+
const level = resolveNumberingLevel(index(), numId, ilvl)?.level;
|
|
2614
|
+
return level ? { lvlText: level.lvlText, numFmt: level.numFmt } : null;
|
|
2615
|
+
},
|
|
2616
|
+
runsXml: (paragraphId) => {
|
|
2617
|
+
const node = findNode2(root(), paragraphId);
|
|
2618
|
+
return node ? paragraphRunsXml(node) : null;
|
|
2619
|
+
}
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
// src/docx/beforeSave.ts
|
|
2624
|
+
var hooks = /* @__PURE__ */ new WeakMap();
|
|
2625
|
+
function onBeforeSave(editor, fn) {
|
|
2626
|
+
let set = hooks.get(editor);
|
|
2627
|
+
if (!set) hooks.set(editor, set = /* @__PURE__ */ new Set());
|
|
2628
|
+
set.add(fn);
|
|
2629
|
+
return () => set.delete(fn);
|
|
2630
|
+
}
|
|
2631
|
+
function runBeforeSave(editor) {
|
|
2632
|
+
if (!editor) return;
|
|
2633
|
+
for (const fn of hooks.get(editor) ?? [])
|
|
2634
|
+
try {
|
|
2635
|
+
fn();
|
|
2636
|
+
} catch {
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
var DEFAULT_CROSS_REFERENCES_LABELS = {
|
|
2640
|
+
insert: "Insert cross-reference",
|
|
2641
|
+
title: "Insert cross-reference",
|
|
2642
|
+
description: "Refer to a clause of this document, or to a passage of another document.",
|
|
2643
|
+
thisDocument: "This document",
|
|
2644
|
+
otherDocument: "Another document",
|
|
2645
|
+
filterTargets: "Find a clause or heading",
|
|
2646
|
+
noTargets: "This document has no numbered clauses or headings yet.",
|
|
2647
|
+
number: "Paragraph number",
|
|
2648
|
+
text: "Heading text",
|
|
2649
|
+
insertAs: "Insert",
|
|
2650
|
+
chooseDocument: "Choose a document",
|
|
2651
|
+
filterPassages: "Find a passage",
|
|
2652
|
+
loadingPassages: "Loading passages\u2026",
|
|
2653
|
+
noPassages: "No passage matches.",
|
|
2654
|
+
referenceText: "Reference text",
|
|
2655
|
+
insertButton: "Insert",
|
|
2656
|
+
cancel: "Cancel",
|
|
2657
|
+
clause: (number) => `Clause ${number}`,
|
|
2658
|
+
heading: "Heading",
|
|
2659
|
+
update: "Update cross-references",
|
|
2660
|
+
updated: "Cross-references updated",
|
|
2661
|
+
updateSummary: (refreshed) => refreshed ? `${refreshed} cross-reference${refreshed === 1 ? "" : "s"} brought up to date.` : "Every cross-reference is up to date.",
|
|
2662
|
+
brokenTitle: "Broken cross-references",
|
|
2663
|
+
brokenNone: "No cross-reference points at a deleted target.",
|
|
2664
|
+
brokenHelp: "Their target was deleted: the last text is kept and marked. Insert the reference again to repair it.",
|
|
2665
|
+
brokenCard: "Broken cross-reference",
|
|
2666
|
+
brokenCardBody: "Its target was deleted. Update cross-references to mark it.",
|
|
2667
|
+
show: "Show",
|
|
2668
|
+
close: "Close"
|
|
2669
|
+
};
|
|
2670
|
+
var CrossReferencesContext = createContext(null);
|
|
2671
|
+
var useCrossReferences = () => useContext(CrossReferencesContext);
|
|
2672
|
+
function CrossReferencesProvider({
|
|
2673
|
+
children,
|
|
2674
|
+
editable,
|
|
2675
|
+
references,
|
|
2676
|
+
documentId,
|
|
2677
|
+
notify,
|
|
2678
|
+
labels
|
|
2679
|
+
}) {
|
|
2680
|
+
const editor = useDocxEditor();
|
|
2681
|
+
const track = useTrackedOrNoted();
|
|
2682
|
+
const l = useMemo(() => ({ ...DEFAULT_CROSS_REFERENCES_LABELS, ...labels }), [labels]);
|
|
2683
|
+
const [dialog, setDialog] = useState(
|
|
2684
|
+
null
|
|
2685
|
+
);
|
|
2686
|
+
const marker = useRef(null);
|
|
2687
|
+
const [viewer, setViewer] = useState(null);
|
|
2688
|
+
useEffect(() => setViewer(marker.current?.closest(".native-docx-viewer") ?? null), []);
|
|
2689
|
+
const openDialog = useCallback(() => {
|
|
2690
|
+
if (!editor || !editable) return;
|
|
2691
|
+
try {
|
|
2692
|
+
const port = referencesPort(editor);
|
|
2693
|
+
const caret = port.caret();
|
|
2694
|
+
if (!caret) return notify?.("Place the cursor where the reference should go.", "error");
|
|
2695
|
+
setDialog({ caret, targets: listTargets(port.paragraphs(), port.listItems(), port.levelOf) });
|
|
2696
|
+
} catch (error) {
|
|
2697
|
+
notify?.(error instanceof Error ? error.message : "Could not read the document.", "error");
|
|
2698
|
+
}
|
|
2699
|
+
}, [editor, editable, notify]);
|
|
2700
|
+
const run2 = useCallback(
|
|
2701
|
+
(label, prepare, insert) => {
|
|
2702
|
+
if (!editor) return;
|
|
2703
|
+
try {
|
|
2704
|
+
const prepared = withDirectEditing(editor, prepare);
|
|
2705
|
+
if (dialog) referencesPort(editor).setCaret(dialog.caret);
|
|
2706
|
+
track({ label, insert: (revision) => insert(prepared, revision), inserted: () => true });
|
|
2707
|
+
setDialog(null);
|
|
2708
|
+
editor.surface?.focus();
|
|
2709
|
+
holdCaret(editor);
|
|
2710
|
+
} catch (error) {
|
|
2711
|
+
notify?.(
|
|
2712
|
+
error instanceof Error ? error.message : "Could not insert the reference.",
|
|
2713
|
+
"error"
|
|
2714
|
+
);
|
|
2715
|
+
}
|
|
2716
|
+
},
|
|
2717
|
+
[editor, dialog, track, notify]
|
|
2718
|
+
);
|
|
2719
|
+
useEffect(() => {
|
|
2720
|
+
if (!editor || !editable) return;
|
|
2721
|
+
const refresh = () => {
|
|
2722
|
+
try {
|
|
2723
|
+
const port = referencesPort(editor);
|
|
2724
|
+
if (!port.paragraphs().some((p) => p.fields?.length)) return;
|
|
2725
|
+
preservingCaret(editor, () => withDirectEditing(editor, () => refreshCrossReferences(port)));
|
|
2726
|
+
} catch {
|
|
2727
|
+
}
|
|
2728
|
+
};
|
|
2729
|
+
const off = onBeforeSave(editor, refresh);
|
|
2730
|
+
const timer = setTimeout(refresh, 1500);
|
|
2731
|
+
return () => {
|
|
2732
|
+
off();
|
|
2733
|
+
clearTimeout(timer);
|
|
2734
|
+
};
|
|
2735
|
+
}, [editor, editable]);
|
|
2736
|
+
const [report, setReport] = useState(null);
|
|
2737
|
+
const update = useCallback(() => {
|
|
2738
|
+
if (!editor || !editable) return;
|
|
2739
|
+
try {
|
|
2740
|
+
const result = preservingCaret(
|
|
2741
|
+
editor,
|
|
2742
|
+
() => withDirectEditing(editor, () => refreshCrossReferences(referencesPort(editor)))
|
|
2743
|
+
);
|
|
2744
|
+
setReport(result);
|
|
2745
|
+
} catch (error) {
|
|
2746
|
+
notify?.(
|
|
2747
|
+
error instanceof Error ? error.message : "Could not update cross-references.",
|
|
2748
|
+
"error"
|
|
2749
|
+
);
|
|
2750
|
+
}
|
|
2751
|
+
}, [editor, editable, notify]);
|
|
2752
|
+
const [passages, setPassages] = useState({});
|
|
2753
|
+
const loadPassages = useCallback(
|
|
2754
|
+
(id) => {
|
|
2755
|
+
if (!references || passages[id]) return;
|
|
2756
|
+
setPassages((p) => ({ ...p, [id]: "loading" }));
|
|
2757
|
+
references.passages(id).then((list) => setPassages((p) => ({ ...p, [id]: list }))).catch(() => setPassages((p) => ({ ...p, [id]: [] })));
|
|
2758
|
+
},
|
|
2759
|
+
[references, passages]
|
|
2760
|
+
);
|
|
2761
|
+
useEffect(() => {
|
|
2762
|
+
if (!viewer || !references) return;
|
|
2763
|
+
const targetOf = (event) => {
|
|
2764
|
+
const link = event.target?.closest?.(
|
|
2765
|
+
'a.docx-hyperlink[data-docx-link-kind="external"]'
|
|
2766
|
+
);
|
|
2767
|
+
if (!link || !viewer.contains(link)) return null;
|
|
2768
|
+
const mouse = event;
|
|
2769
|
+
if (mouse.button !== 0 || mouse.ctrlKey || mouse.metaKey || mouse.shiftKey) return null;
|
|
2770
|
+
return references.targetOf(link.getAttribute("href") ?? "");
|
|
2771
|
+
};
|
|
2772
|
+
const take = (event) => {
|
|
2773
|
+
const target = targetOf(event);
|
|
2774
|
+
if (!target) return;
|
|
2775
|
+
event.preventDefault();
|
|
2776
|
+
event.stopPropagation();
|
|
2777
|
+
if (event.type === "click") references.open(target);
|
|
2778
|
+
};
|
|
2779
|
+
const types = ["pointerdown", "mousedown", "pointerup", "mouseup", "click"];
|
|
2780
|
+
for (const type of types) window.addEventListener(type, take, true);
|
|
2781
|
+
return () => {
|
|
2782
|
+
for (const type of types) window.removeEventListener(type, take, true);
|
|
2783
|
+
};
|
|
2784
|
+
}, [viewer, references]);
|
|
2785
|
+
const value = useMemo(
|
|
2786
|
+
() => editable ? { openDialog, update, labels: l } : null,
|
|
2787
|
+
[editable, openDialog, update, l]
|
|
2788
|
+
);
|
|
2789
|
+
const resolveInternal = (href) => {
|
|
2790
|
+
if (!editor) return null;
|
|
2791
|
+
const name = href.replace(/^#/, "");
|
|
2792
|
+
try {
|
|
2793
|
+
const port = referencesPort(editor);
|
|
2794
|
+
const paragraphs = port.paragraphs();
|
|
2795
|
+
const target = paragraphs.find((p) => p.bookmarks.includes(name));
|
|
2796
|
+
if (!target) return { title: l.brokenCard, body: l.brokenCardBody };
|
|
2797
|
+
const number = paragraphNumber(
|
|
2798
|
+
paragraphs.map((p) => p.id),
|
|
2799
|
+
port.listItems(),
|
|
2800
|
+
port.levelOf,
|
|
2801
|
+
target.id
|
|
2802
|
+
);
|
|
2803
|
+
return {
|
|
2804
|
+
title: number ? l.clause(number) : l.heading,
|
|
2805
|
+
body: passageExcerpt(target.text.replace(//g, ""))
|
|
2806
|
+
};
|
|
2807
|
+
} catch {
|
|
2808
|
+
return null;
|
|
2809
|
+
}
|
|
2810
|
+
};
|
|
2811
|
+
return /* @__PURE__ */ jsxs(CrossReferencesContext.Provider, { value, children: [
|
|
2812
|
+
/* @__PURE__ */ jsx("span", { ref: marker, hidden: true }),
|
|
2813
|
+
children,
|
|
2814
|
+
/* @__PURE__ */ jsx(
|
|
2815
|
+
LinkHoverCard,
|
|
2816
|
+
{
|
|
2817
|
+
root: viewer,
|
|
2818
|
+
matches: (href) => href.startsWith(`#${REF_BOOKMARK_PREFIX}`),
|
|
2819
|
+
resolve: resolveInternal,
|
|
2820
|
+
testId: "docx-cross-reference-card"
|
|
2821
|
+
}
|
|
2822
|
+
),
|
|
2823
|
+
references && /* @__PURE__ */ jsx(
|
|
2824
|
+
LinkHoverCard,
|
|
2825
|
+
{
|
|
2826
|
+
root: viewer,
|
|
2827
|
+
matches: (href) => !!references.targetOf(href),
|
|
2828
|
+
resolve: (href) => {
|
|
2829
|
+
const target = references.targetOf(href);
|
|
2830
|
+
if (!target) return null;
|
|
2831
|
+
const list = passages[target.documentId];
|
|
2832
|
+
if (!list) loadPassages(target.documentId);
|
|
2833
|
+
const passage = Array.isArray(list) ? list.find((p) => p.chunkId === target.chunkId) : void 0;
|
|
2834
|
+
return passage ? {
|
|
2835
|
+
body: passageExcerpt(passage.text),
|
|
2836
|
+
footer: passage.page ? `p. ${passage.page}` : void 0
|
|
2837
|
+
} : null;
|
|
2838
|
+
},
|
|
2839
|
+
testId: "docx-cross-reference-card"
|
|
2840
|
+
}
|
|
2841
|
+
),
|
|
2842
|
+
dialog && /* @__PURE__ */ jsx(
|
|
2843
|
+
CrossReferenceDialog,
|
|
2844
|
+
{
|
|
2845
|
+
targets: dialog.targets,
|
|
2846
|
+
references,
|
|
2847
|
+
documentId,
|
|
2848
|
+
passages,
|
|
2849
|
+
loadPassages,
|
|
2850
|
+
labels: l,
|
|
2851
|
+
onCancel: () => setDialog(null),
|
|
2852
|
+
onClosed: () => editor?.surface?.focus(),
|
|
2853
|
+
onInsertTarget: (target, mode) => run2(
|
|
2854
|
+
`Inserted cross-reference: ${refResult(target, mode)}`,
|
|
2855
|
+
() => markCrossReferenceTarget(referencesPort(editor), target, mode),
|
|
2856
|
+
(marked, revision) => insertCrossReferenceField(referencesPort(editor, revision), marked, dialog.caret)
|
|
2857
|
+
),
|
|
2858
|
+
onInsertPassage: (target, text) => run2(
|
|
2859
|
+
`Inserted cross-reference: ${text}`,
|
|
2860
|
+
() => void 0,
|
|
2861
|
+
(_, revision) => insertDocumentReference(
|
|
2862
|
+
referencesPort(editor, revision),
|
|
2863
|
+
{ text, url: references.linkFor(target), appName: references.appName },
|
|
2864
|
+
dialog.caret
|
|
2865
|
+
)
|
|
2866
|
+
)
|
|
2867
|
+
}
|
|
2868
|
+
),
|
|
2869
|
+
/* @__PURE__ */ jsx(Dialog, { open: !!report, onOpenChange: (open) => !open && setReport(null), children: /* @__PURE__ */ jsxs(
|
|
2870
|
+
DialogContent,
|
|
2871
|
+
{
|
|
2872
|
+
className: "max-h-[85dvh] overflow-y-auto",
|
|
2873
|
+
"data-testid": "docx-cross-references-report",
|
|
2874
|
+
children: [
|
|
2875
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2876
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: l.updated }),
|
|
2877
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: report && l.updateSummary(report.refreshed) })
|
|
2878
|
+
] }),
|
|
2879
|
+
report && /* @__PURE__ */ jsxs("section", { className: "space-y-1 text-sm", children: [
|
|
2880
|
+
/* @__PURE__ */ jsx("h3", { className: "font-medium", children: l.brokenTitle }),
|
|
2881
|
+
report.broken.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2882
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: l.brokenHelp }),
|
|
2883
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-1", "data-testid": "docx-cross-references-broken", children: report.broken.map((b) => /* @__PURE__ */ jsxs(
|
|
2884
|
+
"li",
|
|
2885
|
+
{
|
|
2886
|
+
className: "flex items-center justify-between gap-2",
|
|
2887
|
+
children: [
|
|
2888
|
+
/* @__PURE__ */ jsx("span", { className: "text-red-text", children: b.text }),
|
|
2889
|
+
/* @__PURE__ */ jsx(
|
|
2890
|
+
Button,
|
|
2891
|
+
{
|
|
2892
|
+
size: "sm",
|
|
2893
|
+
variant: "ghost",
|
|
2894
|
+
onClick: () => {
|
|
2895
|
+
const point = { paragraphId: b.paragraphId, offset: b.offset };
|
|
2896
|
+
editor?.surface?.setSelection({ anchor: point, head: point });
|
|
2897
|
+
editor?.surface?.revealParagraph(b.paragraphId);
|
|
2898
|
+
setReport(null);
|
|
2899
|
+
},
|
|
2900
|
+
children: l.show
|
|
2901
|
+
}
|
|
2902
|
+
)
|
|
2903
|
+
]
|
|
2904
|
+
},
|
|
2905
|
+
`${b.paragraphId}:${b.offset}`
|
|
2906
|
+
)) })
|
|
2907
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: l.brokenNone })
|
|
2908
|
+
] }),
|
|
2909
|
+
/* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => setReport(null), children: l.close }) })
|
|
2910
|
+
]
|
|
2911
|
+
}
|
|
2912
|
+
) })
|
|
2913
|
+
] });
|
|
2914
|
+
}
|
|
2915
|
+
function CrossReferenceDialog({
|
|
2916
|
+
targets,
|
|
2917
|
+
references,
|
|
2918
|
+
documentId,
|
|
2919
|
+
passages,
|
|
2920
|
+
loadPassages,
|
|
2921
|
+
labels,
|
|
2922
|
+
onCancel,
|
|
2923
|
+
onInsertTarget,
|
|
2924
|
+
onInsertPassage,
|
|
2925
|
+
onClosed
|
|
2926
|
+
}) {
|
|
2927
|
+
const l = { ...DEFAULT_CROSS_REFERENCES_LABELS, ...labels };
|
|
2928
|
+
const [tab, setTab] = useState("this");
|
|
2929
|
+
const [query, setQuery] = useState("");
|
|
2930
|
+
const [chosen, setChosen] = useState(null);
|
|
2931
|
+
const [mode, setMode] = useState("number");
|
|
2932
|
+
const shown = useMemo(() => filterTargets(targets, query), [targets, query]);
|
|
2933
|
+
const effectiveMode = chosen?.number ? mode : "text";
|
|
2934
|
+
const [documents, setDocuments] = useState(null);
|
|
2935
|
+
const [docId, setDocId] = useState(null);
|
|
2936
|
+
const [passageQuery, setPassageQuery] = useState("");
|
|
2937
|
+
const [passage, setPassage] = useState(null);
|
|
2938
|
+
const [text, setText] = useState("");
|
|
2939
|
+
useEffect(() => {
|
|
2940
|
+
if (tab !== "other" || !references || documents) return;
|
|
2941
|
+
references.documents().then((list2) => setDocuments(list2.filter((d) => d.id !== documentId))).catch(() => setDocuments([]));
|
|
2942
|
+
}, [tab, references, documents, documentId]);
|
|
2943
|
+
const chooseDocument = (id) => {
|
|
2944
|
+
setDocId(id);
|
|
2945
|
+
setPassage(null);
|
|
2946
|
+
setText("");
|
|
2947
|
+
loadPassages(id);
|
|
2948
|
+
};
|
|
2949
|
+
const title = documents?.find((d) => d.id === docId)?.title ?? "";
|
|
2950
|
+
const list = docId ? passages[docId] : void 0;
|
|
2951
|
+
const shownPassages = Array.isArray(list) ? filterPassages(list, passageQuery) : [];
|
|
2952
|
+
const canInsert = tab === "this" ? !!chosen : !!(docId && passage && text.trim());
|
|
2953
|
+
const insert = () => {
|
|
2954
|
+
if (tab === "this" && chosen) onInsertTarget(chosen, effectiveMode);
|
|
2955
|
+
if (tab === "other" && docId && passage)
|
|
2956
|
+
onInsertPassage(
|
|
2957
|
+
{ documentId: docId, chunkId: passage.chunkId, page: passage.page ?? null },
|
|
2958
|
+
text
|
|
2959
|
+
);
|
|
2960
|
+
};
|
|
2961
|
+
return /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: (open) => !open && onCancel(), children: /* @__PURE__ */ jsxs(
|
|
2962
|
+
DialogContent,
|
|
2963
|
+
{
|
|
2964
|
+
className: "max-h-[85dvh] overflow-y-auto",
|
|
2965
|
+
"data-testid": "docx-cross-reference-dialog",
|
|
2966
|
+
onCloseAutoFocus: (event) => {
|
|
2967
|
+
if (!onClosed) return;
|
|
2968
|
+
event.preventDefault();
|
|
2969
|
+
onClosed();
|
|
2970
|
+
},
|
|
2971
|
+
children: [
|
|
2972
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2973
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: l.title }),
|
|
2974
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: l.description })
|
|
2975
|
+
] }),
|
|
2976
|
+
/* @__PURE__ */ jsxs(Tabs, { value: tab, onValueChange: (v) => setTab(v), children: [
|
|
2977
|
+
/* @__PURE__ */ jsxs(TabsList, { children: [
|
|
2978
|
+
/* @__PURE__ */ jsx(TabsTrigger, { value: "this", "data-testid": "docx-cross-reference-this", children: l.thisDocument }),
|
|
2979
|
+
references && /* @__PURE__ */ jsx(TabsTrigger, { value: "other", "data-testid": "docx-cross-reference-other", children: l.otherDocument })
|
|
2980
|
+
] }),
|
|
2981
|
+
/* @__PURE__ */ jsxs(TabsContent, { value: "this", className: "space-y-3", children: [
|
|
2982
|
+
/* @__PURE__ */ jsx(
|
|
2983
|
+
Input,
|
|
2984
|
+
{
|
|
2985
|
+
value: query,
|
|
2986
|
+
placeholder: l.filterTargets,
|
|
2987
|
+
"aria-label": l.filterTargets,
|
|
2988
|
+
onChange: (e) => setQuery(e.target.value),
|
|
2989
|
+
"data-testid": "docx-cross-reference-filter"
|
|
2990
|
+
}
|
|
2991
|
+
),
|
|
2992
|
+
/* @__PURE__ */ jsxs(
|
|
2993
|
+
"div",
|
|
2994
|
+
{
|
|
2995
|
+
role: "listbox",
|
|
2996
|
+
"aria-label": l.filterTargets,
|
|
2997
|
+
className: "max-h-64 space-y-0.5 overflow-y-auto rounded-md border border-border p-1",
|
|
2998
|
+
children: [
|
|
2999
|
+
shown.length === 0 && /* @__PURE__ */ jsx("p", { className: "p-2 text-sm text-muted-foreground", children: l.noTargets }),
|
|
3000
|
+
shown.map((t) => /* @__PURE__ */ jsxs(
|
|
3001
|
+
"button",
|
|
3002
|
+
{
|
|
3003
|
+
type: "button",
|
|
3004
|
+
role: "option",
|
|
3005
|
+
"aria-selected": chosen?.paragraphId === t.paragraphId,
|
|
3006
|
+
"data-testid": "docx-cross-reference-target",
|
|
3007
|
+
onClick: () => setChosen(t),
|
|
3008
|
+
onDoubleClick: () => onInsertTarget(t, t.number ? mode : "text"),
|
|
3009
|
+
className: cn(
|
|
3010
|
+
"flex w-full items-baseline gap-2 rounded px-2 py-1 text-left text-sm",
|
|
3011
|
+
chosen?.paragraphId === t.paragraphId ? "bg-accent" : "hover:bg-accent/50"
|
|
3012
|
+
),
|
|
3013
|
+
style: { paddingLeft: 8 + t.level * 16 },
|
|
3014
|
+
children: [
|
|
3015
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: t.marker || l.heading }),
|
|
3016
|
+
/* @__PURE__ */ jsx("span", { className: cn("truncate", t.heading && "font-medium"), children: t.text })
|
|
3017
|
+
]
|
|
3018
|
+
},
|
|
3019
|
+
t.paragraphId
|
|
3020
|
+
))
|
|
3021
|
+
]
|
|
3022
|
+
}
|
|
3023
|
+
),
|
|
3024
|
+
chosen && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 text-sm", children: [
|
|
3025
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: l.insertAs }),
|
|
3026
|
+
chosen.number && /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
|
|
3027
|
+
/* @__PURE__ */ jsx(
|
|
3028
|
+
"input",
|
|
3029
|
+
{
|
|
3030
|
+
type: "radio",
|
|
3031
|
+
name: "cross-reference-mode",
|
|
3032
|
+
checked: effectiveMode === "number",
|
|
3033
|
+
onChange: () => setMode("number")
|
|
3034
|
+
}
|
|
3035
|
+
),
|
|
3036
|
+
l.number
|
|
3037
|
+
] }),
|
|
3038
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
|
|
3039
|
+
/* @__PURE__ */ jsx(
|
|
3040
|
+
"input",
|
|
3041
|
+
{
|
|
3042
|
+
type: "radio",
|
|
3043
|
+
name: "cross-reference-mode",
|
|
3044
|
+
checked: effectiveMode === "text",
|
|
3045
|
+
onChange: () => setMode("text")
|
|
3046
|
+
}
|
|
3047
|
+
),
|
|
3048
|
+
l.text
|
|
3049
|
+
] }),
|
|
3050
|
+
/* @__PURE__ */ jsx(
|
|
3051
|
+
"span",
|
|
3052
|
+
{
|
|
3053
|
+
className: "ml-auto rounded bg-muted px-2 py-0.5",
|
|
3054
|
+
"data-testid": "docx-cross-reference-preview",
|
|
3055
|
+
children: refResult(chosen, effectiveMode)
|
|
3056
|
+
}
|
|
3057
|
+
)
|
|
3058
|
+
] })
|
|
3059
|
+
] }),
|
|
3060
|
+
references && /* @__PURE__ */ jsxs(TabsContent, { value: "other", className: "space-y-3", children: [
|
|
3061
|
+
references.renderDocumentPicker ? references.renderDocumentPicker(chooseDocument, docId) : /* @__PURE__ */ jsxs(
|
|
3062
|
+
"select",
|
|
3063
|
+
{
|
|
3064
|
+
className: "h-9 w-full rounded-md border border-border bg-background px-2 text-sm",
|
|
3065
|
+
"aria-label": l.chooseDocument,
|
|
3066
|
+
value: docId ?? "",
|
|
3067
|
+
onChange: (e) => e.target.value && chooseDocument(e.target.value),
|
|
3068
|
+
"data-testid": "docx-cross-reference-document",
|
|
3069
|
+
children: [
|
|
3070
|
+
/* @__PURE__ */ jsx("option", { value: "", children: l.chooseDocument }),
|
|
3071
|
+
(documents ?? []).map((d) => /* @__PURE__ */ jsx("option", { value: d.id, children: d.title }, d.id))
|
|
3072
|
+
]
|
|
3073
|
+
}
|
|
3074
|
+
),
|
|
3075
|
+
docId && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3076
|
+
/* @__PURE__ */ jsx(
|
|
3077
|
+
Input,
|
|
3078
|
+
{
|
|
3079
|
+
value: passageQuery,
|
|
3080
|
+
placeholder: l.filterPassages,
|
|
3081
|
+
"aria-label": l.filterPassages,
|
|
3082
|
+
onChange: (e) => setPassageQuery(e.target.value),
|
|
3083
|
+
"data-testid": "docx-cross-reference-passage-filter"
|
|
3084
|
+
}
|
|
3085
|
+
),
|
|
3086
|
+
/* @__PURE__ */ jsx(
|
|
3087
|
+
"div",
|
|
3088
|
+
{
|
|
3089
|
+
className: "max-h-64 space-y-1 overflow-y-auto",
|
|
3090
|
+
"data-testid": "docx-cross-reference-passages",
|
|
3091
|
+
children: list === "loading" || list === void 0 ? /* @__PURE__ */ jsx("p", { className: "p-2 text-sm text-muted-foreground", children: l.loadingPassages }) : shownPassages.length === 0 ? /* @__PURE__ */ jsx("p", { className: "p-2 text-sm text-muted-foreground", children: l.noPassages }) : shownPassages.map((p, i) => /* @__PURE__ */ jsx(
|
|
3092
|
+
FactPassageItem,
|
|
3093
|
+
{
|
|
3094
|
+
index: i,
|
|
3095
|
+
page: p.page,
|
|
3096
|
+
excerpt: passageExcerpt(p.text, 200),
|
|
3097
|
+
isViewing: passage?.chunkId === p.chunkId,
|
|
3098
|
+
onSelect: () => {
|
|
3099
|
+
setPassage(p);
|
|
3100
|
+
setText(referenceText(title, p));
|
|
3101
|
+
},
|
|
3102
|
+
testId: "docx-cross-reference-passage"
|
|
3103
|
+
},
|
|
3104
|
+
p.chunkId
|
|
3105
|
+
))
|
|
3106
|
+
}
|
|
3107
|
+
),
|
|
3108
|
+
passage && /* @__PURE__ */ jsxs("label", { className: "block space-y-1 text-sm", children: [
|
|
3109
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: l.referenceText }),
|
|
3110
|
+
/* @__PURE__ */ jsx(
|
|
3111
|
+
Input,
|
|
3112
|
+
{
|
|
3113
|
+
value: text,
|
|
3114
|
+
onChange: (e) => setText(e.target.value),
|
|
3115
|
+
"data-testid": "docx-cross-reference-text"
|
|
3116
|
+
}
|
|
3117
|
+
)
|
|
3118
|
+
] })
|
|
3119
|
+
] })
|
|
3120
|
+
] })
|
|
3121
|
+
] }),
|
|
3122
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
3123
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onCancel, children: l.cancel }),
|
|
3124
|
+
/* @__PURE__ */ jsx(Button, { disabled: !canInsert, onClick: insert, "data-testid": "docx-cross-reference-insert", children: l.insertButton })
|
|
3125
|
+
] })
|
|
3126
|
+
]
|
|
3127
|
+
}
|
|
3128
|
+
) });
|
|
3129
|
+
}
|
|
2166
3130
|
function RibbonMenu({
|
|
2167
3131
|
label,
|
|
2168
3132
|
icon,
|
|
2169
3133
|
children,
|
|
2170
3134
|
className,
|
|
2171
3135
|
testId,
|
|
2172
|
-
title
|
|
3136
|
+
title,
|
|
3137
|
+
keepMounted = false,
|
|
3138
|
+
popoverClassName
|
|
2173
3139
|
}) {
|
|
2174
3140
|
const [open, setOpen] = useState(false);
|
|
2175
3141
|
const element = useRef(null);
|
|
@@ -2203,12 +3169,13 @@ function RibbonMenu({
|
|
|
2203
3169
|
children: icon
|
|
2204
3170
|
}
|
|
2205
3171
|
),
|
|
2206
|
-
open && /* @__PURE__ */ jsx(
|
|
3172
|
+
(open || keepMounted) && /* @__PURE__ */ jsx(
|
|
2207
3173
|
"div",
|
|
2208
3174
|
{
|
|
2209
|
-
className: "native-docx-ribbon-popover",
|
|
3175
|
+
className: ["native-docx-ribbon-popover", popoverClassName].filter(Boolean).join(" "),
|
|
2210
3176
|
role: "group",
|
|
2211
3177
|
"aria-label": label,
|
|
3178
|
+
hidden: !open,
|
|
2212
3179
|
onMouseDown: (event) => {
|
|
2213
3180
|
if (!(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement))
|
|
2214
3181
|
event.preventDefault();
|
|
@@ -2298,7 +3265,7 @@ function GenerateImageButton({ generation }) {
|
|
|
2298
3265
|
});
|
|
2299
3266
|
const editable = useEditorState((snapshot) => snapshot.editable);
|
|
2300
3267
|
const generating = useSyncExternalStore(subscribe, () => running > 0);
|
|
2301
|
-
async function
|
|
3268
|
+
async function run2() {
|
|
2302
3269
|
if (!editor || !prompt.trim() || busy) return;
|
|
2303
3270
|
const caret = rememberCaret(editor);
|
|
2304
3271
|
const controller = new AbortController();
|
|
@@ -2344,7 +3311,7 @@ function GenerateImageButton({ generation }) {
|
|
|
2344
3311
|
className: "native-docx-form native-docx-generate-image",
|
|
2345
3312
|
onSubmit: (event) => {
|
|
2346
3313
|
event.preventDefault();
|
|
2347
|
-
void
|
|
3314
|
+
void run2();
|
|
2348
3315
|
},
|
|
2349
3316
|
children: [
|
|
2350
3317
|
/* @__PURE__ */ jsxs("label", { children: [
|
|
@@ -2360,7 +3327,7 @@ function GenerateImageButton({ generation }) {
|
|
|
2360
3327
|
"data-testid": "docx-generate-image-prompt",
|
|
2361
3328
|
onChange: (event) => setPrompt(event.target.value),
|
|
2362
3329
|
onKeyDown: (event) => {
|
|
2363
|
-
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) void
|
|
3330
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) void run2();
|
|
2364
3331
|
}
|
|
2365
3332
|
}
|
|
2366
3333
|
)
|
|
@@ -2486,6 +3453,163 @@ var WordDraftStream = class {
|
|
|
2486
3453
|
}
|
|
2487
3454
|
};
|
|
2488
3455
|
|
|
3456
|
+
// src/docx/overflowPlan.ts
|
|
3457
|
+
function planOverflow(items, available, moreWidth) {
|
|
3458
|
+
const collapsed = /* @__PURE__ */ new Set();
|
|
3459
|
+
let used = items.reduce((sum, item) => sum + item.width, 0);
|
|
3460
|
+
if (used <= available) return collapsed;
|
|
3461
|
+
used += moreWidth;
|
|
3462
|
+
const order = items.map((item, index) => ({ item, index })).sort((a, b) => a.item.priority - b.item.priority || b.index - a.index);
|
|
3463
|
+
for (const { item } of order) {
|
|
3464
|
+
if (used <= available) break;
|
|
3465
|
+
collapsed.add(item.id);
|
|
3466
|
+
used -= item.width;
|
|
3467
|
+
}
|
|
3468
|
+
return collapsed;
|
|
3469
|
+
}
|
|
3470
|
+
var Overflow = createContext(null);
|
|
3471
|
+
var MORE_WIDTH = 32;
|
|
3472
|
+
var sameSet = (a, b) => a.size === b.size && [...a].every((id) => b.has(id));
|
|
3473
|
+
function RibbonOverflow({ tab, children }) {
|
|
3474
|
+
const row = useRef(null);
|
|
3475
|
+
const items = useRef(/* @__PURE__ */ new Map());
|
|
3476
|
+
const widths = useRef(/* @__PURE__ */ new Map());
|
|
3477
|
+
const [version, setVersion] = useState(0);
|
|
3478
|
+
const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
|
|
3479
|
+
const [slots, setSlots] = useState({});
|
|
3480
|
+
const [menu, setMenu] = useState([]);
|
|
3481
|
+
const register = useCallback((id, item) => {
|
|
3482
|
+
items.current.set(id, item);
|
|
3483
|
+
setVersion((v) => v + 1);
|
|
3484
|
+
return () => {
|
|
3485
|
+
if (items.current.get(id) === item) items.current.delete(id);
|
|
3486
|
+
setVersion((v) => v + 1);
|
|
3487
|
+
};
|
|
3488
|
+
}, []);
|
|
3489
|
+
const plan = useCallback(() => {
|
|
3490
|
+
const element = row.current;
|
|
3491
|
+
if (!element) return;
|
|
3492
|
+
const gap = parseFloat(getComputedStyle(element).columnGap) || 0;
|
|
3493
|
+
const ordered = Array.from(element.querySelectorAll("[data-ribbon-item]")).map((node) => node.dataset.ribbonItem).filter((id) => items.current.has(id));
|
|
3494
|
+
const measured = ordered.map((id) => {
|
|
3495
|
+
const { element: node, priority } = items.current.get(id);
|
|
3496
|
+
if (!node.hidden) {
|
|
3497
|
+
const width = node.getBoundingClientRect().width;
|
|
3498
|
+
widths.current.set(id, width ? width + gap : 0);
|
|
3499
|
+
}
|
|
3500
|
+
return { id, priority, width: widths.current.get(id) ?? 0 };
|
|
3501
|
+
});
|
|
3502
|
+
const next = planOverflow(measured, element.clientWidth, MORE_WIDTH);
|
|
3503
|
+
setCollapsed((current) => sameSet(current, next) ? current : next);
|
|
3504
|
+
const entries = ordered.filter((id) => next.has(id)).map((id) => ({ id, label: items.current.get(id).label }));
|
|
3505
|
+
setMenu(
|
|
3506
|
+
(current) => current.length === entries.length && current.every((entry, i) => entry.id === entries[i].id && entry.label === entries[i].label) ? current : entries
|
|
3507
|
+
);
|
|
3508
|
+
}, []);
|
|
3509
|
+
useLayoutEffect(plan, [plan, version, tab, collapsed]);
|
|
3510
|
+
useLayoutEffect(() => {
|
|
3511
|
+
const element = row.current;
|
|
3512
|
+
if (!element) return;
|
|
3513
|
+
const observer = new ResizeObserver(() => plan());
|
|
3514
|
+
observer.observe(element);
|
|
3515
|
+
for (const item of items.current.values()) observer.observe(item.element);
|
|
3516
|
+
return () => observer.disconnect();
|
|
3517
|
+
}, [plan, version]);
|
|
3518
|
+
const slotRef = useCallback(
|
|
3519
|
+
(id) => (node) => setSlots((current) => {
|
|
3520
|
+
if (node ? current[id] === node : !(id in current)) return current;
|
|
3521
|
+
const next = { ...current };
|
|
3522
|
+
if (node) next[id] = node;
|
|
3523
|
+
else delete next[id];
|
|
3524
|
+
return next;
|
|
3525
|
+
}),
|
|
3526
|
+
[]
|
|
3527
|
+
);
|
|
3528
|
+
const context = useMemo(() => ({ collapsed, slots, register }), [collapsed, slots, register]);
|
|
3529
|
+
const shown = menu.filter((entry) => collapsed.has(entry.id));
|
|
3530
|
+
return /* @__PURE__ */ jsx(Overflow.Provider, { value: context, children: /* @__PURE__ */ jsxs("div", { className: "native-docx-ribbon-row", ref: row, "data-testid": "docx-ribbon-row", children: [
|
|
3531
|
+
children,
|
|
3532
|
+
shown.length > 0 && /* @__PURE__ */ jsx(
|
|
3533
|
+
RibbonMenu,
|
|
3534
|
+
{
|
|
3535
|
+
label: "More",
|
|
3536
|
+
title: "More commands",
|
|
3537
|
+
icon: /* @__PURE__ */ jsx(Ellipsis, { size: 16 }),
|
|
3538
|
+
testId: "docx-ribbon-more",
|
|
3539
|
+
keepMounted: true,
|
|
3540
|
+
popoverClassName: "native-docx-ribbon-more",
|
|
3541
|
+
children: (close) => /* @__PURE__ */ jsx(MoreRows, { entries: shown, slotRef, close })
|
|
3542
|
+
},
|
|
3543
|
+
tab
|
|
3544
|
+
)
|
|
3545
|
+
] }) });
|
|
3546
|
+
}
|
|
3547
|
+
function MoreRows({
|
|
3548
|
+
entries,
|
|
3549
|
+
slotRef,
|
|
3550
|
+
close
|
|
3551
|
+
}) {
|
|
3552
|
+
const refs = useRef(/* @__PURE__ */ new Map());
|
|
3553
|
+
const refFor = (id) => {
|
|
3554
|
+
let ref = refs.current.get(id);
|
|
3555
|
+
if (!ref) refs.current.set(id, ref = slotRef(id));
|
|
3556
|
+
return ref;
|
|
3557
|
+
};
|
|
3558
|
+
const list = useRef(null);
|
|
3559
|
+
const latest = useRef(close);
|
|
3560
|
+
latest.current = close;
|
|
3561
|
+
useEffect(() => {
|
|
3562
|
+
const element = list.current;
|
|
3563
|
+
if (!element) return;
|
|
3564
|
+
const onClick = (event) => {
|
|
3565
|
+
const target = event.target;
|
|
3566
|
+
const row = target.closest(".native-docx-ribbon-more-row");
|
|
3567
|
+
if (!row) return;
|
|
3568
|
+
const control = row.querySelector(".native-docx-ribbon-more-control");
|
|
3569
|
+
if (!control.contains(target)) {
|
|
3570
|
+
control.querySelector("button:not([disabled])")?.click();
|
|
3571
|
+
return;
|
|
3572
|
+
}
|
|
3573
|
+
const button = target.closest("button");
|
|
3574
|
+
if (button && !button.disabled && !control.querySelector(".native-docx-ribbon-popover")?.contains(button) && !button.hasAttribute("aria-expanded") && !button.hasAttribute("aria-haspopup"))
|
|
3575
|
+
latest.current();
|
|
3576
|
+
};
|
|
3577
|
+
element.addEventListener("click", onClick, true);
|
|
3578
|
+
return () => element.removeEventListener("click", onClick, true);
|
|
3579
|
+
}, []);
|
|
3580
|
+
return /* @__PURE__ */ jsx("div", { className: "native-docx-ribbon-more-list", ref: list, children: entries.map((entry) => /* @__PURE__ */ jsxs("div", { className: "native-docx-ribbon-more-row", "data-ribbon-more": entry.id, children: [
|
|
3581
|
+
/* @__PURE__ */ jsx("span", { className: "native-docx-ribbon-more-control", ref: refFor(entry.id) }),
|
|
3582
|
+
/* @__PURE__ */ jsx("span", { className: "native-docx-ribbon-more-label", children: entry.label })
|
|
3583
|
+
] }, entry.id)) });
|
|
3584
|
+
}
|
|
3585
|
+
function RibbonItem({
|
|
3586
|
+
id,
|
|
3587
|
+
label,
|
|
3588
|
+
priority = 0,
|
|
3589
|
+
children
|
|
3590
|
+
}) {
|
|
3591
|
+
const context = useContext(Overflow);
|
|
3592
|
+
const element = useRef(null);
|
|
3593
|
+
const register = context?.register;
|
|
3594
|
+
useLayoutEffect(() => {
|
|
3595
|
+
if (!register || !element.current) return;
|
|
3596
|
+
return register(id, { label, priority, element: element.current });
|
|
3597
|
+
}, [register, id, label, priority]);
|
|
3598
|
+
if (!context) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
3599
|
+
const collapsed = context.collapsed.has(id);
|
|
3600
|
+
const slot = context.slots[id];
|
|
3601
|
+
return /* @__PURE__ */ jsx(
|
|
3602
|
+
"span",
|
|
3603
|
+
{
|
|
3604
|
+
ref: element,
|
|
3605
|
+
className: "native-docx-ribbon-item",
|
|
3606
|
+
"data-ribbon-item": id,
|
|
3607
|
+
hidden: collapsed || void 0,
|
|
3608
|
+
children: collapsed ? slot ? createPortal(children, slot) : null : children
|
|
3609
|
+
}
|
|
3610
|
+
);
|
|
3611
|
+
}
|
|
3612
|
+
|
|
2489
3613
|
// src/docx/wordStyles.ts
|
|
2490
3614
|
var QUICK_STYLES = ["Normal", "Title", "heading 1", "heading 2", "heading 3"];
|
|
2491
3615
|
function findStyle(options, name) {
|
|
@@ -2671,18 +3795,87 @@ function StyleGallery() {
|
|
|
2671
3795
|
}
|
|
2672
3796
|
);
|
|
2673
3797
|
}
|
|
3798
|
+
var W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
3799
|
+
var DEFAULT_PARAGRAPH_FONT = {
|
|
3800
|
+
id: "DefaultParagraphFont",
|
|
3801
|
+
type: "character",
|
|
3802
|
+
xml: '<w:style w:type="character" w:default="1" w:styleId="DefaultParagraphFont"><w:name w:val="Default Paragraph Font"/><w:uiPriority w:val="1"/><w:semiHidden/><w:unhideWhenUsed/></w:style>'
|
|
3803
|
+
};
|
|
3804
|
+
function stylesOf(kind) {
|
|
3805
|
+
const Kind = kind === "footnote" ? "Footnote" : "Endnote";
|
|
3806
|
+
const text = `${Kind}Text`;
|
|
3807
|
+
return [
|
|
3808
|
+
{
|
|
3809
|
+
id: text,
|
|
3810
|
+
type: "paragraph",
|
|
3811
|
+
xml: `<w:style w:type="paragraph" w:styleId="${text}"><w:name w:val="${kind} text"/><w:basedOn w:val="Normal"/><w:link w:val="${text}Char"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:pPr><w:spacing w:after="0" w:line="240" w:lineRule="auto"/></w:pPr><w:rPr><w:sz w:val="20"/><w:szCs w:val="20"/></w:rPr></w:style>`
|
|
3812
|
+
},
|
|
3813
|
+
{
|
|
3814
|
+
id: `${text}Char`,
|
|
3815
|
+
type: "character",
|
|
3816
|
+
xml: `<w:style w:type="character" w:customStyle="1" w:styleId="${text}Char"><w:name w:val="${Kind} Text Char"/><w:basedOn w:val="DefaultParagraphFont"/><w:link w:val="${text}"/><w:uiPriority w:val="99"/><w:semiHidden/><w:rPr><w:sz w:val="20"/><w:szCs w:val="20"/></w:rPr></w:style>`
|
|
3817
|
+
},
|
|
3818
|
+
{
|
|
3819
|
+
id: `${Kind}Reference`,
|
|
3820
|
+
type: "character",
|
|
3821
|
+
xml: `<w:style w:type="character" w:styleId="${Kind}Reference"><w:name w:val="${kind} reference"/><w:basedOn w:val="DefaultParagraphFont"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:rPr><w:vertAlign w:val="superscript"/></w:rPr></w:style>`
|
|
3822
|
+
}
|
|
3823
|
+
];
|
|
3824
|
+
}
|
|
3825
|
+
function noteTextStyle(styles, kind) {
|
|
3826
|
+
const paragraph = styles.filter((style) => style.type === "paragraph");
|
|
3827
|
+
const id = kind === "footnote" ? "FootnoteText" : "EndnoteText";
|
|
3828
|
+
return paragraph.find((style) => style.name.toLowerCase() === `${kind} text`)?.styleId ?? paragraph.find((style) => style.styleId === id)?.styleId;
|
|
3829
|
+
}
|
|
3830
|
+
function missingNoteStyles(styles, kind) {
|
|
3831
|
+
const has = (type, id) => styles.some((style) => style.type === type && style.styleId === id);
|
|
3832
|
+
const text = noteTextStyle(styles, kind);
|
|
3833
|
+
const missing = stylesOf(kind).filter(
|
|
3834
|
+
(style) => style.type === "paragraph" ? !text : !has("character", style.id)
|
|
3835
|
+
);
|
|
3836
|
+
if (!missing.length) return [];
|
|
3837
|
+
const base = has("character", DEFAULT_PARAGRAPH_FONT.id) ? [] : [DEFAULT_PARAGRAPH_FONT];
|
|
3838
|
+
return [...base, ...missing].map((style) => style.xml);
|
|
3839
|
+
}
|
|
3840
|
+
var CONTENT_TYPES = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/></Types>';
|
|
3841
|
+
function stylesOnlyClipboardHtml(styles) {
|
|
3842
|
+
const fragment = zipSync({
|
|
3843
|
+
"[Content_Types].xml": strToU8(CONTENT_TYPES),
|
|
3844
|
+
"_rels/.rels": strToU8(
|
|
3845
|
+
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>'
|
|
3846
|
+
),
|
|
3847
|
+
"word/document.xml": strToU8(
|
|
3848
|
+
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3849
|
+
<w:document xmlns:w="${W}"><w:body><w:p/></w:body></w:document>`
|
|
3850
|
+
),
|
|
3851
|
+
"word/_rels/document.xml.rels": strToU8(
|
|
3852
|
+
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rIdStyles" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships>'
|
|
3853
|
+
),
|
|
3854
|
+
"word/styles.xml": strToU8(
|
|
3855
|
+
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3856
|
+
<w:styles xmlns:w="${W}">${styles.join("")}</w:styles>`
|
|
3857
|
+
)
|
|
3858
|
+
});
|
|
3859
|
+
return fragmentClipboardHtml(fragment, false);
|
|
3860
|
+
}
|
|
3861
|
+
function ensureNoteStyles(editor, kind, direct = (fn) => fn()) {
|
|
3862
|
+
if (!editor.can({ type: "insertNote", noteKind: kind }).ok) return void 0;
|
|
3863
|
+
const missing = missingNoteStyles(editor.getDocumentStyles(), kind);
|
|
3864
|
+
if (missing.length)
|
|
3865
|
+
direct(() => editor.exec({ type: "paste", text: "", html: stylesOnlyClipboardHtml(missing) }));
|
|
3866
|
+
return noteTextStyle(editor.getDocumentStyles(), kind);
|
|
3867
|
+
}
|
|
2674
3868
|
function useInsertNote(kind) {
|
|
2675
3869
|
const command = useEditorCommand(kind === "footnote" ? "insert.footnote" : "insert.endnote");
|
|
2676
|
-
const { options } = useParagraphStyle();
|
|
2677
3870
|
const editor = useDocxEditor();
|
|
2678
3871
|
const insert = () => {
|
|
3872
|
+
const text = editor && ensureNoteStyles(editor, kind, (fn) => withDirectEditing(editor, fn));
|
|
2679
3873
|
if (!command.execute()) return false;
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
);
|
|
3874
|
+
if (editor) {
|
|
3875
|
+
if (text)
|
|
3876
|
+
withDirectEditing(editor, () => editor.exec({ type: "setParagraphStyle", styleId: text }));
|
|
3877
|
+
editor.exec({ type: "insertText", text: " " });
|
|
3878
|
+
}
|
|
2686
3879
|
return true;
|
|
2687
3880
|
};
|
|
2688
3881
|
return { insert, isEnabled: command.isEnabled, disabledReason: command.disabledReason };
|
|
@@ -2694,7 +3887,7 @@ function NoteAction({
|
|
|
2694
3887
|
icon
|
|
2695
3888
|
}) {
|
|
2696
3889
|
const note = useInsertNote(kind);
|
|
2697
|
-
return /* @__PURE__ */ jsx(
|
|
3890
|
+
return /* @__PURE__ */ jsx(RibbonItem, { id: `references-${kind}`, label, children: /* @__PURE__ */ jsx(
|
|
2698
3891
|
DocxEditor.Toolbar.Action,
|
|
2699
3892
|
{
|
|
2700
3893
|
label: `${label} (${shortcut})`,
|
|
@@ -2704,7 +3897,7 @@ function NoteAction({
|
|
|
2704
3897
|
onSelect: () => void note.insert(),
|
|
2705
3898
|
className: `native-docx-insert-${kind}`
|
|
2706
3899
|
}
|
|
2707
|
-
);
|
|
3900
|
+
) });
|
|
2708
3901
|
}
|
|
2709
3902
|
function NoteButtons() {
|
|
2710
3903
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -2774,6 +3967,65 @@ function WordShortcuts({ scope }) {
|
|
|
2774
3967
|
}, [scope]);
|
|
2775
3968
|
return null;
|
|
2776
3969
|
}
|
|
3970
|
+
function CrossReferenceButton() {
|
|
3971
|
+
const references = useCrossReferences();
|
|
3972
|
+
if (!references) return null;
|
|
3973
|
+
return /* @__PURE__ */ jsx(
|
|
3974
|
+
"button",
|
|
3975
|
+
{
|
|
3976
|
+
type: "button",
|
|
3977
|
+
className: "native-docx-ribbon-trigger",
|
|
3978
|
+
"aria-label": references.labels.insert,
|
|
3979
|
+
title: references.labels.insert,
|
|
3980
|
+
"data-testid": "docx-insert-cross-reference",
|
|
3981
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
3982
|
+
onClick: () => references.openDialog(),
|
|
3983
|
+
children: /* @__PURE__ */ jsx(Link2, { size: 16 })
|
|
3984
|
+
}
|
|
3985
|
+
);
|
|
3986
|
+
}
|
|
3987
|
+
function UpdateCrossReferencesButton() {
|
|
3988
|
+
const references = useCrossReferences();
|
|
3989
|
+
if (!references) return null;
|
|
3990
|
+
return /* @__PURE__ */ jsx(
|
|
3991
|
+
"button",
|
|
3992
|
+
{
|
|
3993
|
+
type: "button",
|
|
3994
|
+
className: "native-docx-ribbon-trigger",
|
|
3995
|
+
"aria-label": references.labels.update,
|
|
3996
|
+
title: references.labels.update,
|
|
3997
|
+
"data-testid": "docx-update-cross-references",
|
|
3998
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
3999
|
+
onClick: () => references.update(),
|
|
4000
|
+
children: /* @__PURE__ */ jsx(RefreshCcw, { size: 16 })
|
|
4001
|
+
}
|
|
4002
|
+
);
|
|
4003
|
+
}
|
|
4004
|
+
function DocxContextMenuExtras() {
|
|
4005
|
+
const terms = useDefinedTerms();
|
|
4006
|
+
const references = useCrossReferences();
|
|
4007
|
+
if (!terms && !references) return null;
|
|
4008
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4009
|
+
/* @__PURE__ */ jsx(DocxEditor.ContextMenu.Separator, {}),
|
|
4010
|
+
terms && /* @__PURE__ */ jsx(
|
|
4011
|
+
DocxEditor.ContextMenu.Item,
|
|
4012
|
+
{
|
|
4013
|
+
label: "Insert defined term",
|
|
4014
|
+
icon: /* @__PURE__ */ jsx(BookA, { size: 14 }),
|
|
4015
|
+
shortcut: "@@",
|
|
4016
|
+
onSelect: () => terms.openPicker()
|
|
4017
|
+
}
|
|
4018
|
+
),
|
|
4019
|
+
references && /* @__PURE__ */ jsx(
|
|
4020
|
+
DocxEditor.ContextMenu.Item,
|
|
4021
|
+
{
|
|
4022
|
+
label: references.labels.insert,
|
|
4023
|
+
icon: /* @__PURE__ */ jsx(Link2, { size: 14 }),
|
|
4024
|
+
onSelect: () => references.openDialog()
|
|
4025
|
+
}
|
|
4026
|
+
)
|
|
4027
|
+
] });
|
|
4028
|
+
}
|
|
2777
4029
|
|
|
2778
4030
|
// src/docx/layout/presets.ts
|
|
2779
4031
|
var TWIPS_PER_INCH = 1440;
|
|
@@ -2989,10 +4241,10 @@ function LayoutButtons() {
|
|
|
2989
4241
|
const [dialog, setDialog] = useState(false);
|
|
2990
4242
|
const props = { setup: pageSetup, apply, openDialog: () => setDialog(true) };
|
|
2991
4243
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2992
|
-
/* @__PURE__ */ jsx(Margins, { ...props }),
|
|
2993
|
-
/* @__PURE__ */ jsx(Orientation, { ...props }),
|
|
2994
|
-
/* @__PURE__ */ jsx(Size, { ...props }),
|
|
2995
|
-
/* @__PURE__ */ jsx(
|
|
4244
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "layout-margins", label: "Margins", children: /* @__PURE__ */ jsx(Margins, { ...props }) }),
|
|
4245
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "layout-orientation", label: "Orientation", children: /* @__PURE__ */ jsx(Orientation, { ...props }) }),
|
|
4246
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "layout-size", label: "Size", children: /* @__PURE__ */ jsx(Size, { ...props }) }),
|
|
4247
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "layout-columns", label: "Columns", children: /* @__PURE__ */ jsx(
|
|
2996
4248
|
DocxEditor.Toolbar.Action,
|
|
2997
4249
|
{
|
|
2998
4250
|
label: "Columns",
|
|
@@ -3001,9 +4253,9 @@ function LayoutButtons() {
|
|
|
3001
4253
|
disabledReason: COLUMNS_UNSUPPORTED,
|
|
3002
4254
|
className: "native-docx-layout-columns"
|
|
3003
4255
|
}
|
|
3004
|
-
),
|
|
3005
|
-
/* @__PURE__ */ jsx(Breaks, {}),
|
|
3006
|
-
/* @__PURE__ */ jsx(
|
|
4256
|
+
) }),
|
|
4257
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "layout-breaks", label: "Breaks", children: /* @__PURE__ */ jsx(Breaks, {}) }),
|
|
4258
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "layout-page-setup", label: "Page Setup\u2026", children: /* @__PURE__ */ jsx(
|
|
3007
4259
|
DocxEditor.Toolbar.Action,
|
|
3008
4260
|
{
|
|
3009
4261
|
label: "Page Setup\u2026",
|
|
@@ -3011,7 +4263,7 @@ function LayoutButtons() {
|
|
|
3011
4263
|
onSelect: () => setDialog(true),
|
|
3012
4264
|
className: "native-docx-layout-page-setup"
|
|
3013
4265
|
}
|
|
3014
|
-
),
|
|
4266
|
+
) }),
|
|
3015
4267
|
/* @__PURE__ */ jsx(DocxEditor.PageSetupDialog, { open: dialog, onClose: () => setDialog(false) })
|
|
3016
4268
|
] });
|
|
3017
4269
|
}
|
|
@@ -3038,7 +4290,7 @@ function CommandGallery({
|
|
|
3038
4290
|
rows
|
|
3039
4291
|
}) {
|
|
3040
4292
|
const bound = useRows(rows);
|
|
3041
|
-
return /* @__PURE__ */ jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsx(
|
|
4293
|
+
return /* @__PURE__ */ jsx(RibbonItem, { id: testId, label, children: /* @__PURE__ */ jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsx(
|
|
3042
4294
|
RibbonGallery,
|
|
3043
4295
|
{
|
|
3044
4296
|
label,
|
|
@@ -3052,7 +4304,7 @@ function CommandGallery({
|
|
|
3052
4304
|
})),
|
|
3053
4305
|
onPick: (id) => void bound.find((row) => row.id === id)?.state.execute()
|
|
3054
4306
|
}
|
|
3055
|
-
) });
|
|
4307
|
+
) }) });
|
|
3056
4308
|
}
|
|
3057
4309
|
function CommandAction({
|
|
3058
4310
|
command,
|
|
@@ -3061,7 +4313,7 @@ function CommandAction({
|
|
|
3061
4313
|
testId
|
|
3062
4314
|
}) {
|
|
3063
4315
|
const state = useEditorCommand(command);
|
|
3064
|
-
return /* @__PURE__ */ jsx(
|
|
4316
|
+
return /* @__PURE__ */ jsx(RibbonItem, { id: `table-${testId}`, label, children: /* @__PURE__ */ jsx(
|
|
3065
4317
|
DocxEditor.Toolbar.Action,
|
|
3066
4318
|
{
|
|
3067
4319
|
label,
|
|
@@ -3072,7 +4324,7 @@ function CommandAction({
|
|
|
3072
4324
|
onSelect: () => void state.execute(),
|
|
3073
4325
|
className: `native-docx-table-${testId}`
|
|
3074
4326
|
}
|
|
3075
|
-
);
|
|
4327
|
+
) });
|
|
3076
4328
|
}
|
|
3077
4329
|
function TableButtons() {
|
|
3078
4330
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -3172,11 +4424,11 @@ function TableButtons() {
|
|
|
3172
4424
|
]
|
|
3173
4425
|
}
|
|
3174
4426
|
),
|
|
3175
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderTarget, {}),
|
|
3176
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderStyle, {}),
|
|
3177
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderWidth, {}),
|
|
3178
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderColor, {}),
|
|
3179
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, {})
|
|
4427
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "table-border-target", label: "Borders", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderTarget, {}) }),
|
|
4428
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "table-border-style", label: "Border style", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderStyle, {}) }),
|
|
4429
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "table-border-width", label: "Border width", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderWidth, {}) }),
|
|
4430
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "table-border-color", label: "Border color", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderColor, {}) }),
|
|
4431
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "table-cell-fill", label: "Shading", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, {}) })
|
|
3180
4432
|
] });
|
|
3181
4433
|
}
|
|
3182
4434
|
var CAPTION_LABELS = ["Figure", "Table", "Equation"];
|
|
@@ -3208,9 +4460,9 @@ function countSeqFields(root, label, throughId) {
|
|
|
3208
4460
|
return count;
|
|
3209
4461
|
}
|
|
3210
4462
|
function captionParagraphXml(label, number, text) {
|
|
3211
|
-
const
|
|
4463
|
+
const run2 = (value) => `<w:r><w:t xml:space="preserve">${esc(value)}</w:t></w:r>`;
|
|
3212
4464
|
const rest = text.trim() ? `: ${text.trim()}` : "";
|
|
3213
|
-
return `<w:p><w:pPr><w:pStyle w:val="Caption"/></w:pPr>${
|
|
4465
|
+
return `<w:p><w:pPr><w:pStyle w:val="Caption"/></w:pPr>${run2(`${label} `)}<w:fldSimple w:instr=" SEQ ${esc(label)} \\* ARABIC "><w:r><w:t>${number}</w:t></w:r></w:fldSimple>${rest ? run2(rest) : ""}</w:p>`;
|
|
3214
4466
|
}
|
|
3215
4467
|
function base642(bytes) {
|
|
3216
4468
|
let binary = "";
|
|
@@ -3239,7 +4491,7 @@ function TransformAction({
|
|
|
3239
4491
|
icon
|
|
3240
4492
|
}) {
|
|
3241
4493
|
const state = useEditorCommand(TRANSFORMS[action]);
|
|
3242
|
-
return /* @__PURE__ */ jsx(
|
|
4494
|
+
return /* @__PURE__ */ jsx(RibbonItem, { id: `picture-${action}`, label, children: /* @__PURE__ */ jsx(
|
|
3243
4495
|
DocxEditor.Toolbar.Action,
|
|
3244
4496
|
{
|
|
3245
4497
|
label,
|
|
@@ -3249,7 +4501,7 @@ function TransformAction({
|
|
|
3249
4501
|
onSelect: () => void state.execute(),
|
|
3250
4502
|
className: `native-docx-picture-${action}`
|
|
3251
4503
|
}
|
|
3252
|
-
);
|
|
4504
|
+
) });
|
|
3253
4505
|
}
|
|
3254
4506
|
function insertCaption(editor, label, text, track) {
|
|
3255
4507
|
const surface = editor.surface;
|
|
@@ -3347,9 +4599,9 @@ function CaptionButton({ defaultLabel = "Figure" }) {
|
|
|
3347
4599
|
}
|
|
3348
4600
|
function PictureButtons() {
|
|
3349
4601
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3350
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageWrap, {}),
|
|
3351
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageProperties, {}),
|
|
3352
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageAltText, {}),
|
|
4602
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "picture-wrap", label: "Wrap text", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageWrap, {}) }),
|
|
4603
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "picture-properties", label: "Size and position", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageProperties, {}) }),
|
|
4604
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "picture-alt-text", label: "Alt text", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageAltText, {}) }),
|
|
3353
4605
|
/* @__PURE__ */ jsx(TransformAction, { action: "rotateCW", label: "Rotate right 90\xB0", icon: /* @__PURE__ */ jsx(RotateCw, { size: 16 }) }),
|
|
3354
4606
|
/* @__PURE__ */ jsx(TransformAction, { action: "rotateCCW", label: "Rotate left 90\xB0", icon: /* @__PURE__ */ jsx(RotateCcw, { size: 16 }) }),
|
|
3355
4607
|
/* @__PURE__ */ jsx(
|
|
@@ -3361,7 +4613,7 @@ function PictureButtons() {
|
|
|
3361
4613
|
}
|
|
3362
4614
|
),
|
|
3363
4615
|
/* @__PURE__ */ jsx(TransformAction, { action: "flipV", label: "Flip vertical", icon: /* @__PURE__ */ jsx(FlipVertical2, { size: 16 }) }),
|
|
3364
|
-
/* @__PURE__ */ jsx(CaptionButton, {})
|
|
4616
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "picture-caption", label: "Insert caption", children: /* @__PURE__ */ jsx(CaptionButton, {}) })
|
|
3365
4617
|
] });
|
|
3366
4618
|
}
|
|
3367
4619
|
var LAYOUT_TAB = "Layout";
|
|
@@ -3562,7 +4814,7 @@ function covered(room, vector, receipt) {
|
|
|
3562
4814
|
}
|
|
3563
4815
|
return true;
|
|
3564
4816
|
}
|
|
3565
|
-
var EditorBoundary = class extends
|
|
4817
|
+
var EditorBoundary = class extends React4.Component {
|
|
3566
4818
|
state = {};
|
|
3567
4819
|
static getDerivedStateFromError(error) {
|
|
3568
4820
|
return { error };
|
|
@@ -3624,46 +4876,53 @@ function DocxRibbon({
|
|
|
3624
4876
|
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Undo, {}),
|
|
3625
4877
|
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Redo, {}),
|
|
3626
4878
|
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Save, {}),
|
|
3627
|
-
|
|
3628
|
-
/* @__PURE__ */
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
/* @__PURE__ */ jsx(
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
4879
|
+
/* @__PURE__ */ jsxs(RibbonOverflow, { tab, children: [
|
|
4880
|
+
tab === "Home" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4881
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "home-style", label: "Styles", priority: 80, children: /* @__PURE__ */ jsx(StyleGallery, {}) }),
|
|
4882
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "home-bold", label: "Bold", priority: 100, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Bold, {}) }),
|
|
4883
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "home-italic", label: "Italic", priority: 95, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Italic, {}) }),
|
|
4884
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "home-underline", label: "Underline", priority: 90, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Underline, {}) }),
|
|
4885
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "home-font", label: "Font", priority: 60, children: /* @__PURE__ */ jsxs(RibbonMenu, { label: "Font", icon: /* @__PURE__ */ jsx(Type, { size: 16 }), children: [
|
|
4886
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.FontFamily, {}),
|
|
4887
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.FontSize, {}),
|
|
4888
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.FontColor, {}),
|
|
4889
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Highlight, {})
|
|
4890
|
+
] }) }),
|
|
4891
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "home-more-formatting", label: "More formatting", priority: 50, children: /* @__PURE__ */ jsxs(RibbonMenu, { label: "More formatting", icon: /* @__PURE__ */ jsx(Pilcrow, { size: 16 }), children: [
|
|
4892
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Alignment, {}),
|
|
4893
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.BulletList, {}),
|
|
4894
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.NumberedList, {}),
|
|
4895
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.LineSpacing, {}),
|
|
4896
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Indent, {}),
|
|
4897
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Outdent, {}),
|
|
4898
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Strike, {}),
|
|
4899
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.ClearFormatting, {})
|
|
4900
|
+
] }) })
|
|
4901
|
+
] }),
|
|
4902
|
+
tab === "Insert" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4903
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-table", label: "Table", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableInsert, {}) }),
|
|
4904
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-picture", label: "Picture", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageInsert, {}) }),
|
|
4905
|
+
imageGeneration && /* @__PURE__ */ jsx(RibbonItem, { id: "insert-generate-image", label: "Generate image", children: /* @__PURE__ */ jsx(GenerateImageButton, { generation: imageGeneration }) }),
|
|
4906
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-page-break", label: "Page break", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Button, { slotId: "insert.pageBreak" }) }),
|
|
4907
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-link", label: "Link", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Link, {}) }),
|
|
4908
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-defined-term", label: "Defined term", children: /* @__PURE__ */ jsx(DefinedTermButtons, {}) }),
|
|
4909
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-quick-parts", label: "Quick Parts", children: /* @__PURE__ */ jsx(QuickParts, {}) }),
|
|
4910
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "insert-cross-reference", label: "Cross-reference", children: /* @__PURE__ */ jsx(CrossReferenceButton, {}) })
|
|
3637
4911
|
] }),
|
|
3638
|
-
/* @__PURE__ */
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
/* @__PURE__ */ jsx(
|
|
3642
|
-
/* @__PURE__ */ jsx(
|
|
3643
|
-
/* @__PURE__ */ jsx(
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.
|
|
4912
|
+
/* @__PURE__ */ jsx(LayoutTabContent, { tab }),
|
|
4913
|
+
tab === "Design" && /* @__PURE__ */ jsx(RibbonItem, { id: "design-house-template", label: "House template", children: /* @__PURE__ */ jsx(HouseTemplatePanel, {}) }),
|
|
4914
|
+
tab === "References" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4915
|
+
/* @__PURE__ */ jsx(NoteButtons, {}),
|
|
4916
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "references-cross-reference", label: "Cross-reference", children: /* @__PURE__ */ jsx(CrossReferenceButton, {}) }),
|
|
4917
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "references-update-cross-references", label: "Update cross-references", children: /* @__PURE__ */ jsx(UpdateCrossReferencesButton, {}) })
|
|
4918
|
+
] }),
|
|
4919
|
+
tab === "Review" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4920
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "review-editing-mode", label: "Editing mode", priority: 10, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.EditingMode, {}) }),
|
|
4921
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "review-comments", label: "Comments", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Comments, {}) }),
|
|
4922
|
+
/* @__PURE__ */ jsx(RibbonItem, { id: "review-options", label: "Review options", children: /* @__PURE__ */ jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsx(UsersRound, { size: 16 }), children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Reviewers, {}) }) })
|
|
3647
4923
|
] })
|
|
3648
4924
|
] }),
|
|
3649
|
-
|
|
3650
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableInsert, {}),
|
|
3651
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageInsert, {}),
|
|
3652
|
-
imageGeneration && /* @__PURE__ */ jsx(GenerateImageButton, { generation: imageGeneration }),
|
|
3653
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Button, { slotId: "insert.pageBreak" }),
|
|
3654
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Link, {}),
|
|
3655
|
-
/* @__PURE__ */ jsx(DefinedTermButtons, {}),
|
|
3656
|
-
/* @__PURE__ */ jsx(QuickParts, {})
|
|
3657
|
-
] }),
|
|
3658
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, { hidden: true }),
|
|
3659
|
-
/* @__PURE__ */ jsx(LayoutTabContent, { tab }),
|
|
3660
|
-
tab === "Design" && /* @__PURE__ */ jsx(HouseTemplatePanel, {}),
|
|
3661
|
-
tab === "References" && /* @__PURE__ */ jsx(NoteButtons, {}),
|
|
3662
|
-
tab === "Review" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3663
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.EditingMode, {}),
|
|
3664
|
-
/* @__PURE__ */ jsx(DocxEditor.Toolbar.Comments, {}),
|
|
3665
|
-
/* @__PURE__ */ jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsx(Ellipsis, { size: 16 }), children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Reviewers, {}) })
|
|
3666
|
-
] })
|
|
4925
|
+
/* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, { hidden: true })
|
|
3667
4926
|
] }),
|
|
3668
4927
|
badge && /* @__PURE__ */ jsx("span", { className: "native-docx-ribbon-badge", "data-testid": "docx-ribbon-badge", children: badge })
|
|
3669
4928
|
] });
|
|
@@ -3860,6 +5119,7 @@ function NativeDocxEditor({
|
|
|
3860
5119
|
};
|
|
3861
5120
|
}, [dirty]);
|
|
3862
5121
|
async function exportDocument() {
|
|
5122
|
+
runBeforeSave(ref.current);
|
|
3863
5123
|
const data = await ref.current?.save();
|
|
3864
5124
|
if (!data) return;
|
|
3865
5125
|
const url = URL.createObjectURL(
|
|
@@ -3886,6 +5146,7 @@ function NativeDocxEditor({
|
|
|
3886
5146
|
async function saveVersion() {
|
|
3887
5147
|
if (!ready || saving || stream) return;
|
|
3888
5148
|
setSaving(true);
|
|
5149
|
+
runBeforeSave(ref.current);
|
|
3889
5150
|
const atRevision = revision.current;
|
|
3890
5151
|
try {
|
|
3891
5152
|
const result = isDraft ? await (async () => {
|
|
@@ -4009,7 +5270,7 @@ function NativeDocxEditor({
|
|
|
4009
5270
|
load: adapter.definitions,
|
|
4010
5271
|
editable: !stream && !snapshot && ready.canEdit,
|
|
4011
5272
|
notify: adapter.notify,
|
|
4012
|
-
children: /* @__PURE__ */
|
|
5273
|
+
children: /* @__PURE__ */ jsx(
|
|
4013
5274
|
HouseTemplateProvider,
|
|
4014
5275
|
{
|
|
4015
5276
|
enabled: !stream,
|
|
@@ -4017,67 +5278,76 @@ function NativeDocxEditor({
|
|
|
4017
5278
|
documentId: isDraft || snapshot ? void 0 : documentId,
|
|
4018
5279
|
editable: !stream && !snapshot && ready.canEdit,
|
|
4019
5280
|
notify: adapter.notify,
|
|
4020
|
-
children:
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
5281
|
+
children: /* @__PURE__ */ jsxs(
|
|
5282
|
+
CrossReferencesProvider,
|
|
5283
|
+
{
|
|
5284
|
+
editable: !stream && !snapshot && ready.canEdit,
|
|
5285
|
+
references: adapter.references,
|
|
5286
|
+
documentId,
|
|
5287
|
+
notify: adapter.notify,
|
|
5288
|
+
children: [
|
|
5289
|
+
/* @__PURE__ */ jsx(
|
|
5290
|
+
DocxEditor.RevisionMarkup,
|
|
5291
|
+
{
|
|
5292
|
+
insertions: { mark: "underline", color: "blue" },
|
|
5293
|
+
deletions: { mark: "strikethrough", color: "red" },
|
|
5294
|
+
movedFrom: { mark: "doubleStrikethrough", color: "green" },
|
|
5295
|
+
movedTo: { mark: "doubleUnderline", color: "green" },
|
|
5296
|
+
trackMoves: true
|
|
5297
|
+
}
|
|
5298
|
+
),
|
|
5299
|
+
!stream && /* @__PURE__ */ jsx(
|
|
5300
|
+
DocxRibbon,
|
|
5301
|
+
{
|
|
5302
|
+
onSave: () => void saveVersion(),
|
|
5303
|
+
imageGeneration: adapter.imageGeneration && {
|
|
5304
|
+
notify: adapter.notify,
|
|
5305
|
+
...adapter.imageGeneration
|
|
5306
|
+
},
|
|
5307
|
+
badge: (
|
|
5308
|
+
// Says the document is shared live, in place of a title row above the ribbon.
|
|
5309
|
+
ready.room && ready.canEdit && !snapshot ? /* @__PURE__ */ jsx("span", { title: "Edits sync live with everyone who has this document open", children: "Co-edit mode" }) : void 0
|
|
5310
|
+
)
|
|
5311
|
+
}
|
|
5312
|
+
),
|
|
5313
|
+
!stream && /* @__PURE__ */ jsx(WordShortcuts, { scope: stageRef }),
|
|
5314
|
+
!stream && /* @__PURE__ */ jsx(TableTabKeys, { scope: stageRef }),
|
|
5315
|
+
/* @__PURE__ */ jsxs(
|
|
5316
|
+
"div",
|
|
5317
|
+
{
|
|
5318
|
+
className: "native-docx-stage",
|
|
5319
|
+
ref: stageRef,
|
|
5320
|
+
onMouseDownCapture: (event) => {
|
|
5321
|
+
if (event.button === 2 && ref.current?.getSelectionPlacement())
|
|
5322
|
+
event.preventDefault();
|
|
5323
|
+
},
|
|
5324
|
+
children: [
|
|
5325
|
+
/* @__PURE__ */ jsxs(DocxEditor.Viewport, { className: "native-docx-viewport", children: [
|
|
5326
|
+
/* @__PURE__ */ jsx(DocxEditor.Content, {}),
|
|
5327
|
+
/* @__PURE__ */ jsx(
|
|
5328
|
+
DocxMentions,
|
|
5329
|
+
{
|
|
5330
|
+
initialCommentId,
|
|
5331
|
+
mentions: adapter.mentions,
|
|
5332
|
+
notify: adapter.notify,
|
|
5333
|
+
getAgentStatus: adapter.getAgentStatus,
|
|
5334
|
+
requestAgent: adapter.requestAgent ? (request) => adapter.requestAgent(documentId, request) : void 0,
|
|
5335
|
+
children: /* @__PURE__ */ jsx(DocxEditorReview, { children: () => /* @__PURE__ */ jsx(DocxEditorReview.Card, { children: /* @__PURE__ */ jsx(DocxCommentActivity, {}) }) })
|
|
5336
|
+
}
|
|
5337
|
+
),
|
|
5338
|
+
/* @__PURE__ */ jsx(DocxEditor.HeaderFooterChrome, {}),
|
|
5339
|
+
/* @__PURE__ */ jsx(DocxEditor.NotesChrome, {}),
|
|
5340
|
+
/* @__PURE__ */ jsx(DocxEditor.Equation, {}),
|
|
5341
|
+
/* @__PURE__ */ jsx(DocxEditor.HyperLink, {}),
|
|
5342
|
+
/* @__PURE__ */ jsx(DocxEditor.ContextMenu, { children: /* @__PURE__ */ jsx(DocxContextMenuExtras, {}) })
|
|
5343
|
+
] }),
|
|
5344
|
+
/* @__PURE__ */ jsx(DocxEditor.PageNumber, {})
|
|
5345
|
+
]
|
|
5346
|
+
}
|
|
4042
5347
|
)
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
!stream && /* @__PURE__ */ jsx(TableTabKeys, { scope: stageRef }),
|
|
4047
|
-
/* @__PURE__ */ jsxs(
|
|
4048
|
-
"div",
|
|
4049
|
-
{
|
|
4050
|
-
className: "native-docx-stage",
|
|
4051
|
-
ref: stageRef,
|
|
4052
|
-
onMouseDownCapture: (event) => {
|
|
4053
|
-
if (event.button === 2 && ref.current?.getSelectionPlacement())
|
|
4054
|
-
event.preventDefault();
|
|
4055
|
-
},
|
|
4056
|
-
children: [
|
|
4057
|
-
/* @__PURE__ */ jsxs(DocxEditor.Viewport, { className: "native-docx-viewport", children: [
|
|
4058
|
-
/* @__PURE__ */ jsx(DocxEditor.Content, {}),
|
|
4059
|
-
/* @__PURE__ */ jsx(
|
|
4060
|
-
DocxMentions,
|
|
4061
|
-
{
|
|
4062
|
-
initialCommentId,
|
|
4063
|
-
mentions: adapter.mentions,
|
|
4064
|
-
notify: adapter.notify,
|
|
4065
|
-
getAgentStatus: adapter.getAgentStatus,
|
|
4066
|
-
requestAgent: adapter.requestAgent ? (request) => adapter.requestAgent(documentId, request) : void 0,
|
|
4067
|
-
children: /* @__PURE__ */ jsx(DocxEditorReview, { children: () => /* @__PURE__ */ jsx(DocxEditorReview.Card, { children: /* @__PURE__ */ jsx(DocxCommentActivity, {}) }) })
|
|
4068
|
-
}
|
|
4069
|
-
),
|
|
4070
|
-
/* @__PURE__ */ jsx(DocxEditor.HeaderFooterChrome, {}),
|
|
4071
|
-
/* @__PURE__ */ jsx(DocxEditor.NotesChrome, {}),
|
|
4072
|
-
/* @__PURE__ */ jsx(DocxEditor.Equation, {}),
|
|
4073
|
-
/* @__PURE__ */ jsx(DocxEditor.HyperLink, {}),
|
|
4074
|
-
/* @__PURE__ */ jsx(DocxEditor.ContextMenu, {})
|
|
4075
|
-
] }),
|
|
4076
|
-
/* @__PURE__ */ jsx(DocxEditor.PageNumber, {})
|
|
4077
|
-
]
|
|
4078
|
-
}
|
|
4079
|
-
)
|
|
4080
|
-
]
|
|
5348
|
+
]
|
|
5349
|
+
}
|
|
5350
|
+
)
|
|
4081
5351
|
}
|
|
4082
5352
|
)
|
|
4083
5353
|
}
|
|
@@ -4176,6 +5446,6 @@ async function loadFonts(baseUrl) {
|
|
|
4176
5446
|
};
|
|
4177
5447
|
}
|
|
4178
5448
|
|
|
4179
|
-
export { BUILTIN_TEMPLATE_NAME, DEFAULT_DEFINED_TERMS_LABELS, DEFINED_TERM_TRIGGER, DefinedTermsProvider, DocxAuthorContext, DocxCommentActivity, DocxEditorReview, DocxMentions, DocxParticipants, DocxRibbon, GenerateImageButton, HouseTemplateProvider, NativeDocxEditor, builtinHouseTemplate, contentPath, editorPort, findDefinitionsSection, insertDefinedTerm, loadDocxFonts, normalizeDocxExport, resolveHouseTemplate, reviewModule, structuralPort, templateFileName, trackedOrNoted, useDefinedTerms, useHouseTemplate, useReview, useReviewItem, useTrackedOrNoted, withDirectEditing };
|
|
4180
|
-
//# sourceMappingURL=chunk-
|
|
4181
|
-
//# sourceMappingURL=chunk-
|
|
5449
|
+
export { BUILTIN_TEMPLATE_NAME, CrossReferenceDialog, CrossReferencesProvider, DEFAULT_CROSS_REFERENCES_LABELS, DEFAULT_DEFINED_TERMS_LABELS, DEFINED_TERM_TRIGGER, DefinedTermsProvider, DocxAuthorContext, DocxCommentActivity, DocxEditorReview, DocxMentions, DocxParticipants, DocxRibbon, GenerateImageButton, HouseTemplateProvider, LinkHoverCard, NativeDocxEditor, builtinHouseTemplate, contentPath, editorPort, findDefinitionsSection, insertCrossReference, insertDefinedTerm, insertDocumentReference, listTargets, loadDocxFonts, normalizeDocxExport, paragraphNumber, referenceText, referencesPort, resolveHouseTemplate, reviewModule, shortTitle, structuralPort, templateFileName, trackedOrNoted, useCrossReferences, useDefinedTerms, useHouseTemplate, useReview, useReviewItem, useTrackedOrNoted, withDirectEditing };
|
|
5450
|
+
//# sourceMappingURL=chunk-W2RTZOK3.js.map
|
|
5451
|
+
//# sourceMappingURL=chunk-W2RTZOK3.js.map
|