@arbidocs/blocks 0.4.99 → 0.4.101
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/{chunk-44TPPPRJ.cjs → chunk-FAGQTB3D.cjs} +958 -272
- package/dist/chunk-FAGQTB3D.cjs.map +1 -0
- package/dist/{chunk-C5RF47LD.js → chunk-G5JH2YMQ.js} +3 -3
- package/dist/{chunk-C5RF47LD.js.map → chunk-G5JH2YMQ.js.map} +1 -1
- package/dist/{chunk-4ZTIMQ7Z.js → chunk-MYALCKDR.js} +963 -277
- package/dist/chunk-MYALCKDR.js.map +1 -0
- package/dist/{chunk-MABEOI4S.cjs → chunk-Y5XW57U4.cjs} +5 -5
- package/dist/{chunk-MABEOI4S.cjs.map → chunk-Y5XW57U4.cjs.map} +1 -1
- package/dist/{chunk-3ICWR3BK.js → chunk-YGREW5TZ.js} +3 -3
- package/dist/{chunk-3ICWR3BK.js.map → chunk-YGREW5TZ.js.map} +1 -1
- package/dist/{chunk-QBEUCOC7.cjs → chunk-ZT2EBBSC.cjs} +5 -5
- package/dist/{chunk-QBEUCOC7.cjs.map → chunk-ZT2EBBSC.cjs.map} +1 -1
- package/dist/connect/docx.cjs +6 -6
- package/dist/connect/docx.js +4 -4
- package/dist/connect/index.cjs +3 -3
- package/dist/connect/index.js +2 -2
- package/dist/docx/NativeDocxEditor.d.ts +7 -2
- package/dist/docx/definitions/DefinedTerms.d.ts +1 -12
- package/dist/docx/definitions/commands.d.ts +3 -27
- package/dist/docx/index.cjs +38 -38
- package/dist/docx/index.d.ts +2 -1
- package/dist/docx/index.js +3 -3
- package/dist/docx/layout/GenerateImage.d.ts +50 -0
- package/dist/docx/layout/LayoutRibbon.d.ts +32 -0
- package/dist/docx/layout/LayoutTabs.d.ts +20 -0
- package/dist/docx/layout/PictureRibbon.d.ts +23 -0
- package/dist/docx/layout/TableKeys.d.ts +25 -0
- package/dist/docx/layout/TableRibbon.d.ts +11 -0
- package/dist/docx/layout/caption.d.ts +38 -0
- package/dist/docx/layout/presets.d.ts +40 -0
- package/dist/index.cjs +5 -5
- package/dist/index.js +1 -1
- package/package.json +5 -4
- package/src/docx/README.md +24 -3
- package/src/docx/layout/layout.css +120 -0
- package/src/docx/styles.css +2 -0
- package/dist/chunk-44TPPPRJ.cjs.map +0 -1
- package/dist/chunk-4ZTIMQ7Z.js.map +0 -1
|
@@ -12,6 +12,7 @@ var lucideReact = require('lucide-react');
|
|
|
12
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
13
13
|
var reactDom = require('react-dom');
|
|
14
14
|
var template = require('@arbidocs/coedit/template');
|
|
15
|
+
var editor = require('@docx-editor.dev/core/editor');
|
|
15
16
|
var server = require('react-dom/server');
|
|
16
17
|
var Y = require('yjs');
|
|
17
18
|
var coedit = require('@arbidocs/coedit');
|
|
@@ -896,18 +897,18 @@ function ReviewCardSlot({ children }) {
|
|
|
896
897
|
var DocxEditorReview = Object.assign(DocxEditorReviewRail, { Card: ReviewCardSlot });
|
|
897
898
|
|
|
898
899
|
// src/docx/mentions.ts
|
|
899
|
-
function mentionCandidates(
|
|
900
|
+
function mentionCandidates(mentions) {
|
|
900
901
|
return [
|
|
901
902
|
{ id: "arbi", label: "ARBI", kind: "assistant" },
|
|
902
|
-
...
|
|
903
|
+
...mentions.filter((person) => person.name.trim()).map((person) => ({
|
|
903
904
|
id: person.id,
|
|
904
905
|
label: person.name,
|
|
905
906
|
kind: person.kind === "agent" ? "assistant" : "user"
|
|
906
907
|
}))
|
|
907
908
|
];
|
|
908
909
|
}
|
|
909
|
-
function mentionedDocxRecipients(text,
|
|
910
|
-
return chunk7UTB4PHM_cjs.extractMentions(text, mentionCandidates(
|
|
910
|
+
function mentionedDocxRecipients(text, mentions) {
|
|
911
|
+
return chunk7UTB4PHM_cjs.extractMentions(text, mentionCandidates(mentions)).map((person) => person.id);
|
|
911
912
|
}
|
|
912
913
|
var ActivityContext = React3.createContext({});
|
|
913
914
|
function DocxCommentActivity() {
|
|
@@ -983,7 +984,7 @@ function DocxCommentActivity() {
|
|
|
983
984
|
}
|
|
984
985
|
function DocxMentions({
|
|
985
986
|
children,
|
|
986
|
-
mentions
|
|
987
|
+
mentions = [],
|
|
987
988
|
initialCommentId,
|
|
988
989
|
requestAgent,
|
|
989
990
|
getAgentStatus,
|
|
@@ -1042,7 +1043,7 @@ function DocxMentions({
|
|
|
1042
1043
|
const [suggestions, setSuggestions] = React3.useState(null);
|
|
1043
1044
|
const [selected, setSelected] = React3.useState(0);
|
|
1044
1045
|
const candidates = chunk7UTB4PHM_cjs.filterMentionCandidates(
|
|
1045
|
-
mentionCandidates(
|
|
1046
|
+
mentionCandidates(mentions),
|
|
1046
1047
|
suggestions?.query || ""
|
|
1047
1048
|
).slice(0, 8);
|
|
1048
1049
|
React3.useEffect(() => {
|
|
@@ -1063,7 +1064,7 @@ function DocxMentions({
|
|
|
1063
1064
|
}));
|
|
1064
1065
|
};
|
|
1065
1066
|
const hasAgent = submission.recipientIds.some(
|
|
1066
|
-
(id) => id === "arbi" ||
|
|
1067
|
+
(id) => id === "arbi" || mentions.some((person) => person.id === id && person.kind === "agent")
|
|
1067
1068
|
);
|
|
1068
1069
|
if (hasAgent) update("delivering");
|
|
1069
1070
|
void requestAgent({
|
|
@@ -1097,7 +1098,7 @@ function DocxMentions({
|
|
|
1097
1098
|
"error"
|
|
1098
1099
|
);
|
|
1099
1100
|
});
|
|
1100
|
-
}, [review.items, requestAgent, getAgentStatus,
|
|
1101
|
+
}, [review.items, requestAgent, getAgentStatus, mentions, notify]);
|
|
1101
1102
|
const choose = (name) => {
|
|
1102
1103
|
const field = input.current;
|
|
1103
1104
|
if (!field || !suggestions) return;
|
|
@@ -1115,7 +1116,7 @@ function DocxMentions({
|
|
|
1115
1116
|
'[data-testid="review-draft-input"], [data-testid="review-reply-input"]'
|
|
1116
1117
|
);
|
|
1117
1118
|
if (!field || field.readOnly || !requestAgent) return false;
|
|
1118
|
-
const recipientIds = mentionedDocxRecipients(field.value,
|
|
1119
|
+
const recipientIds = mentionedDocxRecipients(field.value, mentions);
|
|
1119
1120
|
if (!recipientIds.length) return false;
|
|
1120
1121
|
pending.current = {
|
|
1121
1122
|
ids: new Set(review.items.filter((i) => i.kind === "comment").map((i) => i.item.id)),
|
|
@@ -1162,7 +1163,7 @@ function DocxMentions({
|
|
|
1162
1163
|
(entry) => entry.kind === "comment" && entry.parentId === commentId
|
|
1163
1164
|
);
|
|
1164
1165
|
const author = replies.at(-1)?.author || target.author;
|
|
1165
|
-
const agent =
|
|
1166
|
+
const agent = mentions.find((person) => person.kind === "agent" && person.name === author);
|
|
1166
1167
|
if (agent || author === "ARBI" || author === "Assistant")
|
|
1167
1168
|
prefixMention(
|
|
1168
1169
|
field,
|
|
@@ -1240,7 +1241,7 @@ function DocxMentions({
|
|
|
1240
1241
|
onMouseDown: (event) => event.preventDefault(),
|
|
1241
1242
|
onClick: (event) => {
|
|
1242
1243
|
event.stopPropagation();
|
|
1243
|
-
if (!mentionedDocxRecipients(field.value,
|
|
1244
|
+
if (!mentionedDocxRecipients(field.value, mentions).includes("arbi"))
|
|
1244
1245
|
prefixMention(field);
|
|
1245
1246
|
else field.focus();
|
|
1246
1247
|
},
|
|
@@ -1295,7 +1296,6 @@ function definitionTooltip(definition) {
|
|
|
1295
1296
|
const line = `\u201C${definition.term}\u201D${definition.rest}`.replace(/\s+/g, " ").trim();
|
|
1296
1297
|
return line.length > 255 ? `${line.slice(0, 254)}\u2026` : line;
|
|
1297
1298
|
}
|
|
1298
|
-
var definitionParagraphText = (definition) => `\u201C${definition.term}\u201D${definition.rest}`;
|
|
1299
1299
|
function definitionParagraphXml(definition, bookmark, id = 0) {
|
|
1300
1300
|
return `<w:p><w:bookmarkStart w:id="${id}" w:name="${chunkAOFATOT3_cjs.esc(bookmark)}"/>${textRun("\u201C")}${textRun(
|
|
1301
1301
|
definition.term,
|
|
@@ -1416,95 +1416,6 @@ function insertDefinedTerm(port, definition, options = {}) {
|
|
|
1416
1416
|
port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + definition.term.length });
|
|
1417
1417
|
return { addedDefinition };
|
|
1418
1418
|
}
|
|
1419
|
-
var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1420
|
-
var mentions = (text, term) => new RegExp(`(^|[^\\p{L}\\p{N}])${escapeRegExp(term)}($|[^\\p{L}\\p{N}])`, "iu").test(text);
|
|
1421
|
-
function updateDefinitions(port, definitions) {
|
|
1422
|
-
const result = {
|
|
1423
|
-
added: [],
|
|
1424
|
-
refreshed: [],
|
|
1425
|
-
reordered: [],
|
|
1426
|
-
unused: [],
|
|
1427
|
-
unknown: []
|
|
1428
|
-
};
|
|
1429
|
-
let paragraphs = port.paragraphs();
|
|
1430
|
-
const linked = new Set(
|
|
1431
|
-
paragraphs.flatMap(
|
|
1432
|
-
(p) => p.links.map((l) => l.anchor).filter((a) => a.startsWith(chunkAOFATOT3_cjs.DEFINITION_BOOKMARK_PREFIX))
|
|
1433
|
-
)
|
|
1434
|
-
);
|
|
1435
|
-
const declared = /* @__PURE__ */ new Map();
|
|
1436
|
-
for (const p of paragraphs)
|
|
1437
|
-
for (const b of p.bookmarks)
|
|
1438
|
-
if (b.startsWith(chunkAOFATOT3_cjs.DEFINITION_BOOKMARK_PREFIX) && !declared.has(b)) declared.set(b, p);
|
|
1439
|
-
const factOf = (bookmark) => {
|
|
1440
|
-
const id = chunkAOFATOT3_cjs.definitionIdOfBookmark(bookmark);
|
|
1441
|
-
return id ? definitions.get(id) : void 0;
|
|
1442
|
-
};
|
|
1443
|
-
for (const bookmark of [...linked, ...declared.keys()])
|
|
1444
|
-
if (!factOf(bookmark) && !result.unknown.includes(bookmark)) result.unknown.push(bookmark);
|
|
1445
|
-
const section = findDefinitionsSection(paragraphs);
|
|
1446
|
-
const rewrite = /* @__PURE__ */ new Map();
|
|
1447
|
-
for (const [bookmark, paragraph] of declared) {
|
|
1448
|
-
const fact = factOf(bookmark);
|
|
1449
|
-
if (fact && paragraph.text !== definitionParagraphText(fact)) {
|
|
1450
|
-
rewrite.set(paragraph.id, fact);
|
|
1451
|
-
result.refreshed.push(fact.term);
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
if (section) {
|
|
1455
|
-
let previous = null;
|
|
1456
|
-
for (let i = section.start; i < section.end; i++) {
|
|
1457
|
-
const p = paragraphs[i];
|
|
1458
|
-
const term = termOf(p);
|
|
1459
|
-
if (term === null) continue;
|
|
1460
|
-
const bookmark = p.bookmarks.find((b) => b.startsWith(chunkAOFATOT3_cjs.DEFINITION_BOOKMARK_PREFIX));
|
|
1461
|
-
const fact = bookmark ? factOf(bookmark) : void 0;
|
|
1462
|
-
if (previous !== null && chunkAOFATOT3_cjs.compareTerms(term, previous) < 0 && fact) {
|
|
1463
|
-
if (!rewrite.has(p.id)) result.reordered.push(fact.term);
|
|
1464
|
-
rewrite.set(p.id, fact);
|
|
1465
|
-
continue;
|
|
1466
|
-
}
|
|
1467
|
-
previous = term;
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
for (const id of [...rewrite.keys()].reverse()) {
|
|
1471
|
-
const index = paragraphs.findIndex((p) => p.id === id);
|
|
1472
|
-
const previous = paragraphs[index - 1];
|
|
1473
|
-
const target = paragraphs[index];
|
|
1474
|
-
if (!previous) continue;
|
|
1475
|
-
port.deleteRange(
|
|
1476
|
-
{ paragraphId: previous.id, offset: previous.text.length },
|
|
1477
|
-
{ paragraphId: target.id, offset: target.text.length }
|
|
1478
|
-
);
|
|
1479
|
-
paragraphs = port.paragraphs();
|
|
1480
|
-
}
|
|
1481
|
-
const toAdd = [...rewrite.values()];
|
|
1482
|
-
for (const bookmark of linked) {
|
|
1483
|
-
const fact = factOf(bookmark);
|
|
1484
|
-
if (fact && !declared.has(bookmark) && !toAdd.some((d) => d.id === fact.id)) {
|
|
1485
|
-
toAdd.push(fact);
|
|
1486
|
-
result.added.push(fact.term);
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
toAdd.sort((a, b) => chunkAOFATOT3_cjs.compareTerms(a.term, b.term));
|
|
1490
|
-
for (const definition of toAdd) addDefinition(port, definition);
|
|
1491
|
-
paragraphs = port.paragraphs();
|
|
1492
|
-
const after = findDefinitionsSection(paragraphs);
|
|
1493
|
-
if (after) {
|
|
1494
|
-
const inSection = (i) => i >= after.title && i < after.end;
|
|
1495
|
-
const outside = paragraphs.filter((_, i) => !inSection(i));
|
|
1496
|
-
const linkedNow = new Set(outside.flatMap((p) => p.links.map((l) => l.anchor)));
|
|
1497
|
-
const outsideText = outside.map((p) => p.text).join("\n");
|
|
1498
|
-
for (let i = after.start; i < after.end; i++) {
|
|
1499
|
-
const p = paragraphs[i];
|
|
1500
|
-
const term = termOf(p);
|
|
1501
|
-
if (term === null) continue;
|
|
1502
|
-
const used = p.bookmarks.some((b) => linkedNow.has(b)) || mentions(outsideText, term);
|
|
1503
|
-
if (!used) result.unused.push({ term, paragraphId: p.id });
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
return result;
|
|
1507
|
-
}
|
|
1508
1419
|
function definitionOfAnchor(anchor, definitions) {
|
|
1509
1420
|
const id = chunkAOFATOT3_cjs.definitionIdOfBookmark(anchor.replace(/^#/, ""));
|
|
1510
1421
|
return id ? definitions.get(id) : void 0;
|
|
@@ -1712,7 +1623,6 @@ var MAX_GROUPS = 8;
|
|
|
1712
1623
|
var STALE_AFTER_MS = 3e4;
|
|
1713
1624
|
var DEFAULT_DEFINED_TERMS_LABELS = {
|
|
1714
1625
|
insert: "Defined term",
|
|
1715
|
-
update: "Update definitions",
|
|
1716
1626
|
search: "Search defined terms",
|
|
1717
1627
|
allAgreements: "All definitions",
|
|
1718
1628
|
loading: "Loading definitions\u2026",
|
|
@@ -1720,18 +1630,7 @@ var DEFAULT_DEFINED_TERMS_LABELS = {
|
|
|
1720
1630
|
noMatch: "No defined term matches.",
|
|
1721
1631
|
hint: "Enter to insert \xB7 Esc to close",
|
|
1722
1632
|
preferred: "Preferred",
|
|
1723
|
-
alsoIn: (source) => `Also defined${source ? ` in ${source}` : ""}
|
|
1724
|
-
updated: "Definitions updated",
|
|
1725
|
-
updateSummary: (r) => [
|
|
1726
|
-
r.added.length ? `${r.added.length} added` : "",
|
|
1727
|
-
r.refreshed.length ? `${r.refreshed.length} reworded` : "",
|
|
1728
|
-
r.reordered.length ? `${r.reordered.length} reordered` : ""
|
|
1729
|
-
].filter(Boolean).join(" \xB7 ") || "The Definitions section is up to date.",
|
|
1730
|
-
unusedTitle: "Defined but never used",
|
|
1731
|
-
unusedNone: "Every definition in the section is used.",
|
|
1732
|
-
unknownTitle: "Links to definitions that no longer exist",
|
|
1733
|
-
show: "Show",
|
|
1734
|
-
close: "Close"
|
|
1633
|
+
alsoIn: (source) => `Also defined${source ? ` in ${source}` : ""}`
|
|
1735
1634
|
};
|
|
1736
1635
|
var DefinedTermsContext = React3.createContext(null);
|
|
1737
1636
|
var useDefinedTerms = () => React3.useContext(DefinedTermsContext);
|
|
@@ -1757,7 +1656,6 @@ function DefinedTermsProvider({
|
|
|
1757
1656
|
const [labelId, setLabelId] = React3.useState(null);
|
|
1758
1657
|
const [picker, setPicker] = React3.useState(null);
|
|
1759
1658
|
const [selected, setSelected] = React3.useState(0);
|
|
1760
|
-
const [report, setReport] = React3.useState(null);
|
|
1761
1659
|
const marker = React3.useRef(null);
|
|
1762
1660
|
const dismissedAt = React3.useRef(null);
|
|
1763
1661
|
const refresh = React3.useCallback(
|
|
@@ -1916,31 +1814,9 @@ function DefinedTermsProvider({
|
|
|
1916
1814
|
window.addEventListener("keydown", keys, true);
|
|
1917
1815
|
return () => window.removeEventListener("keydown", keys, true);
|
|
1918
1816
|
}, [picker, rows, selected, pick]);
|
|
1919
|
-
const update = React3.useCallback(() => {
|
|
1920
|
-
if (!editor || !editable) return;
|
|
1921
|
-
void refresh(true).then((list) => {
|
|
1922
|
-
const definitions = new Map(
|
|
1923
|
-
list.flatMap((s) => {
|
|
1924
|
-
const d = chunkAOFATOT3_cjs.toDefinition(s);
|
|
1925
|
-
return d ? [[d.id, d]] : [];
|
|
1926
|
-
})
|
|
1927
|
-
);
|
|
1928
|
-
const surface = editor.surface;
|
|
1929
|
-
const before = surface?.state().selection?.head;
|
|
1930
|
-
const paraId = before && surface?.session.paraIdOf(before.paragraphId);
|
|
1931
|
-
const result = run(() => updateDefinitions(editorPort(editor), definitions));
|
|
1932
|
-
const node = paraId && surface?.session.nodeIdOf(paraId);
|
|
1933
|
-
if (result && before && node) {
|
|
1934
|
-
const point = { paragraphId: node, offset: before.offset };
|
|
1935
|
-
surface.setSelection({ anchor: point, head: point });
|
|
1936
|
-
holdCaret(editor);
|
|
1937
|
-
}
|
|
1938
|
-
if (result) setReport(result);
|
|
1939
|
-
});
|
|
1940
|
-
}, [editor, editable, refresh, run]);
|
|
1941
1817
|
const value = React3.useMemo(
|
|
1942
|
-
() => load && editable ? { openPicker,
|
|
1943
|
-
[load, editable, openPicker,
|
|
1818
|
+
() => load && editable ? { openPicker, labels: l } : null,
|
|
1819
|
+
[load, editable, openPicker, l]
|
|
1944
1820
|
);
|
|
1945
1821
|
return /* @__PURE__ */ jsxRuntime.jsxs(DefinedTermsContext.Provider, { value, children: [
|
|
1946
1822
|
/* @__PURE__ */ jsxRuntime.jsx("span", { ref: marker, hidden: true }),
|
|
@@ -1975,50 +1851,7 @@ function DefinedTermsProvider({
|
|
|
1975
1851
|
}
|
|
1976
1852
|
),
|
|
1977
1853
|
document.body
|
|
1978
|
-
)
|
|
1979
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open: !!report, onOpenChange: (open) => !open && setReport(null), children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1980
|
-
ui.DialogContent,
|
|
1981
|
-
{
|
|
1982
|
-
className: "max-h-[85dvh] overflow-y-auto",
|
|
1983
|
-
"data-testid": "docx-definitions-report",
|
|
1984
|
-
children: [
|
|
1985
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.DialogHeader, { children: [
|
|
1986
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.DialogTitle, { children: l.updated }),
|
|
1987
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.DialogDescription, { children: report && l.updateSummary(report) })
|
|
1988
|
-
] }),
|
|
1989
|
-
report && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 text-sm", children: [
|
|
1990
|
-
/* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
|
|
1991
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-1 font-medium", children: l.unusedTitle }),
|
|
1992
|
-
report.unused.length ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", "data-testid": "docx-definitions-unused", children: report.unused.map((u) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-2", children: [
|
|
1993
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: u.term }),
|
|
1994
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1995
|
-
ui.Button,
|
|
1996
|
-
{
|
|
1997
|
-
size: "sm",
|
|
1998
|
-
variant: "ghost",
|
|
1999
|
-
onClick: () => {
|
|
2000
|
-
const surface = editor?.surface;
|
|
2001
|
-
surface?.setSelection({
|
|
2002
|
-
anchor: { paragraphId: u.paragraphId, offset: 0 },
|
|
2003
|
-
head: { paragraphId: u.paragraphId, offset: 0 }
|
|
2004
|
-
});
|
|
2005
|
-
surface?.revealParagraph(u.paragraphId);
|
|
2006
|
-
setReport(null);
|
|
2007
|
-
},
|
|
2008
|
-
children: l.show
|
|
2009
|
-
}
|
|
2010
|
-
)
|
|
2011
|
-
] }, u.paragraphId)) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: l.unusedNone })
|
|
2012
|
-
] }),
|
|
2013
|
-
report.unknown.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
|
|
2014
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-1 font-medium", children: l.unknownTitle }),
|
|
2015
|
-
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "list-disc pl-5 text-muted-foreground", children: report.unknown.map((name) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: name }, name)) })
|
|
2016
|
-
] })
|
|
2017
|
-
] }),
|
|
2018
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "outline", onClick: () => setReport(null), children: l.close }) })
|
|
2019
|
-
]
|
|
2020
|
-
}
|
|
2021
|
-
) })
|
|
1854
|
+
)
|
|
2022
1855
|
] });
|
|
2023
1856
|
}
|
|
2024
1857
|
function DefinedTermMenu({
|
|
@@ -2355,6 +2188,241 @@ function HouseTemplateProvider({
|
|
|
2355
2188
|
);
|
|
2356
2189
|
return /* @__PURE__ */ jsxRuntime.jsx(HouseTemplateContext.Provider, { value: enabled ? value : null, children });
|
|
2357
2190
|
}
|
|
2191
|
+
function RibbonMenu({
|
|
2192
|
+
label,
|
|
2193
|
+
icon,
|
|
2194
|
+
children,
|
|
2195
|
+
className,
|
|
2196
|
+
testId,
|
|
2197
|
+
title
|
|
2198
|
+
}) {
|
|
2199
|
+
const [open, setOpen] = React3.useState(false);
|
|
2200
|
+
const element = React3.useRef(null);
|
|
2201
|
+
React3.useEffect(() => {
|
|
2202
|
+
if (!open) return;
|
|
2203
|
+
const dismiss = (event) => {
|
|
2204
|
+
if (!element.current?.contains(event.target)) setOpen(false);
|
|
2205
|
+
};
|
|
2206
|
+
const escape = (event) => {
|
|
2207
|
+
if (event.key === "Escape") setOpen(false);
|
|
2208
|
+
};
|
|
2209
|
+
document.addEventListener("pointerdown", dismiss);
|
|
2210
|
+
document.addEventListener("keydown", escape);
|
|
2211
|
+
return () => {
|
|
2212
|
+
document.removeEventListener("pointerdown", dismiss);
|
|
2213
|
+
document.removeEventListener("keydown", escape);
|
|
2214
|
+
};
|
|
2215
|
+
}, [open]);
|
|
2216
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-ribbon-menu", ref: element, children: [
|
|
2217
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2218
|
+
"button",
|
|
2219
|
+
{
|
|
2220
|
+
type: "button",
|
|
2221
|
+
className: ["native-docx-ribbon-trigger", className].filter(Boolean).join(" "),
|
|
2222
|
+
"aria-label": label,
|
|
2223
|
+
title: title ?? label,
|
|
2224
|
+
"aria-expanded": open,
|
|
2225
|
+
"data-testid": testId,
|
|
2226
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
2227
|
+
onClick: () => setOpen((value) => !value),
|
|
2228
|
+
children: icon
|
|
2229
|
+
}
|
|
2230
|
+
),
|
|
2231
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2232
|
+
"div",
|
|
2233
|
+
{
|
|
2234
|
+
className: "native-docx-ribbon-popover",
|
|
2235
|
+
role: "group",
|
|
2236
|
+
"aria-label": label,
|
|
2237
|
+
onMouseDown: (event) => {
|
|
2238
|
+
if (!(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement))
|
|
2239
|
+
event.preventDefault();
|
|
2240
|
+
},
|
|
2241
|
+
children: typeof children === "function" ? children(() => setOpen(false)) : children
|
|
2242
|
+
}
|
|
2243
|
+
)
|
|
2244
|
+
] });
|
|
2245
|
+
}
|
|
2246
|
+
var titleOf = (prompt) => {
|
|
2247
|
+
const line = prompt.trim().split("\n")[0];
|
|
2248
|
+
return line.length > 80 ? `${line.slice(0, 79)}\u2026` : line;
|
|
2249
|
+
};
|
|
2250
|
+
function rememberCaret(editor) {
|
|
2251
|
+
const surface = editor.surface;
|
|
2252
|
+
const head = surface?.state().selection?.head;
|
|
2253
|
+
if (!surface || !head) return null;
|
|
2254
|
+
return { paraId: surface.session.paraIdOf(head.paragraphId), ...head };
|
|
2255
|
+
}
|
|
2256
|
+
var mounted = [];
|
|
2257
|
+
var running = 0;
|
|
2258
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
2259
|
+
var setRunning = (delta) => {
|
|
2260
|
+
running += delta;
|
|
2261
|
+
listeners.forEach((listener) => listener());
|
|
2262
|
+
};
|
|
2263
|
+
var subscribe = (listener) => {
|
|
2264
|
+
listeners.add(listener);
|
|
2265
|
+
return () => void listeners.delete(listener);
|
|
2266
|
+
};
|
|
2267
|
+
function insertionTarget(origin, caret, editors = mounted) {
|
|
2268
|
+
if (editors.includes(origin) && origin.surface) return origin;
|
|
2269
|
+
const paraId = caret?.paraId;
|
|
2270
|
+
if (!paraId) return null;
|
|
2271
|
+
for (let i = editors.length - 1; i >= 0; i--) {
|
|
2272
|
+
const session = editors[i].surface?.session;
|
|
2273
|
+
if (session?.nodeIdOf(paraId)) return editors[i];
|
|
2274
|
+
}
|
|
2275
|
+
return null;
|
|
2276
|
+
}
|
|
2277
|
+
function restoreCaret(editor, caret) {
|
|
2278
|
+
const surface = editor.surface;
|
|
2279
|
+
if (!surface || !caret) return;
|
|
2280
|
+
const paragraphId = caret.paraId && surface.session.nodeIdOf(caret.paraId) || caret.paragraphId;
|
|
2281
|
+
if (!surface.session.paragraphIds().includes(paragraphId)) return;
|
|
2282
|
+
const point = { paragraphId, offset: caret.offset };
|
|
2283
|
+
surface.setSelection({ anchor: point, head: point });
|
|
2284
|
+
}
|
|
2285
|
+
async function insertGeneratedImage(editor$1, bytes, prompt, caret) {
|
|
2286
|
+
const image = react.normalizeImageBytes(bytes);
|
|
2287
|
+
if (!image.ok) throw new Error("The generated image is not in a format Word can embed.");
|
|
2288
|
+
let result;
|
|
2289
|
+
for (let attempt = 0; attempt < 3 && !result?.ok; attempt++) {
|
|
2290
|
+
editor$1.focus();
|
|
2291
|
+
restoreCaret(editor$1, caret);
|
|
2292
|
+
result = await editor.executeImageCommand(editor$1, {
|
|
2293
|
+
type: "insertImage",
|
|
2294
|
+
data: image.bytes,
|
|
2295
|
+
mime: image.mime,
|
|
2296
|
+
widthPoints: image.widthPoints,
|
|
2297
|
+
heightPoints: image.heightPoints,
|
|
2298
|
+
description: prompt.trim(),
|
|
2299
|
+
title: titleOf(prompt)
|
|
2300
|
+
});
|
|
2301
|
+
if (!result.ok && result.reason !== "stale drawing selection") break;
|
|
2302
|
+
}
|
|
2303
|
+
if (!result?.ok) throw new Error(result?.reason || "The picture could not be inserted here.");
|
|
2304
|
+
}
|
|
2305
|
+
var AUTO = "";
|
|
2306
|
+
function useGenerateImageTarget() {
|
|
2307
|
+
const editor = react.useDocxEditor();
|
|
2308
|
+
const loaded2 = react.useEditorState((snapshot) => !snapshot.isLoading);
|
|
2309
|
+
React3.useEffect(() => {
|
|
2310
|
+
if (!editor || !loaded2) return;
|
|
2311
|
+
mounted.push(editor);
|
|
2312
|
+
return () => void mounted.splice(mounted.indexOf(editor), 1);
|
|
2313
|
+
}, [editor, loaded2]);
|
|
2314
|
+
}
|
|
2315
|
+
function GenerateImageButton({ generation }) {
|
|
2316
|
+
const editor = react.useDocxEditor();
|
|
2317
|
+
const [prompt, setPrompt] = React3.useState("");
|
|
2318
|
+
const [aspectRatio, setAspectRatio] = React3.useState(AUTO);
|
|
2319
|
+
const [busy, setBusy] = React3.useState(false);
|
|
2320
|
+
const [error, setError] = React3.useState("");
|
|
2321
|
+
const abort = React3.useRef(null);
|
|
2322
|
+
const close = React3.useRef(() => {
|
|
2323
|
+
});
|
|
2324
|
+
const editable = react.useEditorState((snapshot) => snapshot.editable);
|
|
2325
|
+
const generating = React3.useSyncExternalStore(subscribe, () => running > 0);
|
|
2326
|
+
async function run() {
|
|
2327
|
+
if (!editor || !prompt.trim() || busy) return;
|
|
2328
|
+
const caret = rememberCaret(editor);
|
|
2329
|
+
const controller = new AbortController();
|
|
2330
|
+
abort.current = controller;
|
|
2331
|
+
setBusy(true);
|
|
2332
|
+
setRunning(1);
|
|
2333
|
+
setError("");
|
|
2334
|
+
try {
|
|
2335
|
+
const bytes = await generation.generate(prompt.trim(), {
|
|
2336
|
+
aspectRatio: aspectRatio || void 0,
|
|
2337
|
+
signal: controller.signal
|
|
2338
|
+
});
|
|
2339
|
+
if (controller.signal.aborted) return;
|
|
2340
|
+
const target = insertionTarget(editor, caret);
|
|
2341
|
+
if (!target) throw new Error("The document was closed before the generated image was ready.");
|
|
2342
|
+
await insertGeneratedImage(target, bytes, prompt, caret);
|
|
2343
|
+
setPrompt("");
|
|
2344
|
+
close.current();
|
|
2345
|
+
generation.notify?.("Generated image inserted", "success");
|
|
2346
|
+
} catch (failure) {
|
|
2347
|
+
if (controller.signal.aborted) return;
|
|
2348
|
+
const message = failure instanceof Error ? failure.message : String(failure);
|
|
2349
|
+
setError(message);
|
|
2350
|
+
generation.notify?.(message, "error");
|
|
2351
|
+
} finally {
|
|
2352
|
+
abort.current = null;
|
|
2353
|
+
setRunning(-1);
|
|
2354
|
+
setBusy(false);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
if (!editable && !generating) return null;
|
|
2358
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2359
|
+
RibbonMenu,
|
|
2360
|
+
{
|
|
2361
|
+
label: generating ? "Generating image\u2026" : "Generate image",
|
|
2362
|
+
icon: generating ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "native-docx-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 16 }),
|
|
2363
|
+
testId: "docx-generate-image",
|
|
2364
|
+
children: (dismiss) => {
|
|
2365
|
+
close.current = dismiss;
|
|
2366
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2367
|
+
"form",
|
|
2368
|
+
{
|
|
2369
|
+
className: "native-docx-form native-docx-generate-image",
|
|
2370
|
+
onSubmit: (event) => {
|
|
2371
|
+
event.preventDefault();
|
|
2372
|
+
void run();
|
|
2373
|
+
},
|
|
2374
|
+
children: [
|
|
2375
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
2376
|
+
"Describe the image",
|
|
2377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2378
|
+
"textarea",
|
|
2379
|
+
{
|
|
2380
|
+
autoFocus: true,
|
|
2381
|
+
rows: 3,
|
|
2382
|
+
value: prompt,
|
|
2383
|
+
disabled: busy,
|
|
2384
|
+
placeholder: "A watercolour of a lighthouse at dawn",
|
|
2385
|
+
"data-testid": "docx-generate-image-prompt",
|
|
2386
|
+
onChange: (event) => setPrompt(event.target.value),
|
|
2387
|
+
onKeyDown: (event) => {
|
|
2388
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) void run();
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
)
|
|
2392
|
+
] }),
|
|
2393
|
+
generation.aspectRatios && generation.aspectRatios.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
2394
|
+
"Aspect ratio",
|
|
2395
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2396
|
+
"select",
|
|
2397
|
+
{
|
|
2398
|
+
value: aspectRatio,
|
|
2399
|
+
disabled: busy,
|
|
2400
|
+
onChange: (event) => setAspectRatio(event.target.value),
|
|
2401
|
+
children: [
|
|
2402
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: AUTO, children: "Auto" }),
|
|
2403
|
+
generation.aspectRatios.map((ratio) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: ratio.value, children: ratio.label }, ratio.value))
|
|
2404
|
+
]
|
|
2405
|
+
}
|
|
2406
|
+
)
|
|
2407
|
+
] }),
|
|
2408
|
+
busy && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", "data-testid": "docx-generate-image-status", children: "Generating\u2026 the picture is inserted where your cursor was. You can keep writing." }),
|
|
2409
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", children: error }),
|
|
2410
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-form-actions", children: busy ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => abort.current?.abort(), children: "Cancel" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2411
|
+
"button",
|
|
2412
|
+
{
|
|
2413
|
+
type: "submit",
|
|
2414
|
+
disabled: !prompt.trim(),
|
|
2415
|
+
"data-testid": "docx-generate-image-submit",
|
|
2416
|
+
children: "Generate"
|
|
2417
|
+
}
|
|
2418
|
+
) })
|
|
2419
|
+
]
|
|
2420
|
+
}
|
|
2421
|
+
);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
);
|
|
2425
|
+
}
|
|
2358
2426
|
function wordDraftHtml(markdown) {
|
|
2359
2427
|
const template = document.createElement("template");
|
|
2360
2428
|
template.innerHTML = server.renderToStaticMarkup(/* @__PURE__ */ jsxRuntime.jsx(ui.AiMarkdown, { children: markdown }));
|
|
@@ -2442,61 +2510,6 @@ var WordDraftStream = class {
|
|
|
2442
2510
|
}
|
|
2443
2511
|
}
|
|
2444
2512
|
};
|
|
2445
|
-
function RibbonMenu({
|
|
2446
|
-
label,
|
|
2447
|
-
icon,
|
|
2448
|
-
children,
|
|
2449
|
-
className,
|
|
2450
|
-
testId,
|
|
2451
|
-
title
|
|
2452
|
-
}) {
|
|
2453
|
-
const [open, setOpen] = React3.useState(false);
|
|
2454
|
-
const element = React3.useRef(null);
|
|
2455
|
-
React3.useEffect(() => {
|
|
2456
|
-
if (!open) return;
|
|
2457
|
-
const dismiss = (event) => {
|
|
2458
|
-
if (!element.current?.contains(event.target)) setOpen(false);
|
|
2459
|
-
};
|
|
2460
|
-
const escape = (event) => {
|
|
2461
|
-
if (event.key === "Escape") setOpen(false);
|
|
2462
|
-
};
|
|
2463
|
-
document.addEventListener("pointerdown", dismiss);
|
|
2464
|
-
document.addEventListener("keydown", escape);
|
|
2465
|
-
return () => {
|
|
2466
|
-
document.removeEventListener("pointerdown", dismiss);
|
|
2467
|
-
document.removeEventListener("keydown", escape);
|
|
2468
|
-
};
|
|
2469
|
-
}, [open]);
|
|
2470
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-ribbon-menu", ref: element, children: [
|
|
2471
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2472
|
-
"button",
|
|
2473
|
-
{
|
|
2474
|
-
type: "button",
|
|
2475
|
-
className: ["native-docx-ribbon-trigger", className].filter(Boolean).join(" "),
|
|
2476
|
-
"aria-label": label,
|
|
2477
|
-
title: title ?? label,
|
|
2478
|
-
"aria-expanded": open,
|
|
2479
|
-
"data-testid": testId,
|
|
2480
|
-
onMouseDown: (event) => event.preventDefault(),
|
|
2481
|
-
onClick: () => setOpen((value) => !value),
|
|
2482
|
-
children: icon
|
|
2483
|
-
}
|
|
2484
|
-
),
|
|
2485
|
-
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2486
|
-
"div",
|
|
2487
|
-
{
|
|
2488
|
-
className: "native-docx-ribbon-popover",
|
|
2489
|
-
role: "group",
|
|
2490
|
-
"aria-label": label,
|
|
2491
|
-
onMouseDown: (event) => {
|
|
2492
|
-
if (!(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement))
|
|
2493
|
-
event.preventDefault();
|
|
2494
|
-
},
|
|
2495
|
-
children: typeof children === "function" ? children(() => setOpen(false)) : children
|
|
2496
|
-
}
|
|
2497
|
-
)
|
|
2498
|
-
] });
|
|
2499
|
-
}
|
|
2500
2513
|
|
|
2501
2514
|
// src/docx/wordStyles.ts
|
|
2502
2515
|
var QUICK_STYLES = ["Normal", "Title", "heading 1", "heading 2", "heading 3"];
|
|
@@ -2786,6 +2799,679 @@ function WordShortcuts({ scope }) {
|
|
|
2786
2799
|
}, [scope]);
|
|
2787
2800
|
return null;
|
|
2788
2801
|
}
|
|
2802
|
+
|
|
2803
|
+
// src/docx/layout/presets.ts
|
|
2804
|
+
var TWIPS_PER_INCH = 1440;
|
|
2805
|
+
var MARGIN_PRESETS = [
|
|
2806
|
+
{ id: "normal", label: "Normal", top: 1440, right: 1440, bottom: 1440, left: 1440 },
|
|
2807
|
+
{ id: "narrow", label: "Narrow", top: 720, right: 720, bottom: 720, left: 720 },
|
|
2808
|
+
{ id: "moderate", label: "Moderate", top: 1440, right: 1080, bottom: 1440, left: 1080 },
|
|
2809
|
+
{ id: "wide", label: "Wide", top: 1440, right: 2880, bottom: 1440, left: 2880 }
|
|
2810
|
+
];
|
|
2811
|
+
var PAPER_SIZES = [
|
|
2812
|
+
{ id: "letter", label: "Letter", width: 12240, height: 15840 },
|
|
2813
|
+
{ id: "legal", label: "Legal", width: 12240, height: 20160 },
|
|
2814
|
+
{ id: "a4", label: "A4", width: 11906, height: 16838 },
|
|
2815
|
+
{ id: "a5", label: "A5", width: 8391, height: 11906 },
|
|
2816
|
+
{ id: "executive", label: "Executive", width: 10440, height: 15120 }
|
|
2817
|
+
];
|
|
2818
|
+
var TOLERANCE = 20;
|
|
2819
|
+
var near = (a, b) => Math.abs(a - b) <= TOLERANCE;
|
|
2820
|
+
function matchMargins(setup) {
|
|
2821
|
+
if (!setup) return null;
|
|
2822
|
+
const m = setup.marginsTwips;
|
|
2823
|
+
return MARGIN_PRESETS.find(
|
|
2824
|
+
(p) => near(p.top, m.top) && near(p.right, m.right) && near(p.bottom, m.bottom) && near(p.left, m.left)
|
|
2825
|
+
)?.id ?? null;
|
|
2826
|
+
}
|
|
2827
|
+
function matchPaper(setup) {
|
|
2828
|
+
if (!setup) return null;
|
|
2829
|
+
const short = Math.min(setup.pageWidthTwips, setup.pageHeightTwips);
|
|
2830
|
+
const long = Math.max(setup.pageWidthTwips, setup.pageHeightTwips);
|
|
2831
|
+
return PAPER_SIZES.find((p) => near(p.width, short) && near(p.height, long))?.id ?? null;
|
|
2832
|
+
}
|
|
2833
|
+
function orientedSize(paper, orientation) {
|
|
2834
|
+
return orientation === "landscape" ? { pageWidthTwips: paper.height, pageHeightTwips: paper.width } : { pageWidthTwips: paper.width, pageHeightTwips: paper.height };
|
|
2835
|
+
}
|
|
2836
|
+
function inches(twips) {
|
|
2837
|
+
return `${Number((twips / TWIPS_PER_INCH).toFixed(2))}"`;
|
|
2838
|
+
}
|
|
2839
|
+
function paperDescription(paper) {
|
|
2840
|
+
return `${inches(paper.width)} \xD7 ${inches(paper.height)}`;
|
|
2841
|
+
}
|
|
2842
|
+
var COLUMNS_UNSUPPORTED = "Text columns are not available in this editor yet. Documents that already use columns display and save them unchanged.";
|
|
2843
|
+
function RibbonGallery({
|
|
2844
|
+
label,
|
|
2845
|
+
choices,
|
|
2846
|
+
current,
|
|
2847
|
+
onPick,
|
|
2848
|
+
close,
|
|
2849
|
+
testId
|
|
2850
|
+
}) {
|
|
2851
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-gallery", role: "menu", "aria-label": label, "data-testid": testId, children: choices.map((choice) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2852
|
+
"button",
|
|
2853
|
+
{
|
|
2854
|
+
type: "button",
|
|
2855
|
+
role: "menuitemradio",
|
|
2856
|
+
"aria-checked": current === choice.id,
|
|
2857
|
+
disabled: choice.disabled,
|
|
2858
|
+
title: choice.title,
|
|
2859
|
+
"data-choice": choice.id,
|
|
2860
|
+
onClick: () => {
|
|
2861
|
+
onPick(choice.id);
|
|
2862
|
+
close();
|
|
2863
|
+
},
|
|
2864
|
+
children: [
|
|
2865
|
+
choice.icon,
|
|
2866
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "native-docx-gallery-text", children: [
|
|
2867
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-gallery-label", children: choice.label }),
|
|
2868
|
+
choice.detail && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-gallery-detail", children: choice.detail })
|
|
2869
|
+
] })
|
|
2870
|
+
]
|
|
2871
|
+
},
|
|
2872
|
+
choice.id
|
|
2873
|
+
)) });
|
|
2874
|
+
}
|
|
2875
|
+
var marginDetail = (p) => `Top ${inches(p.top)} \xB7 Bottom ${inches(p.bottom)} \xB7 Left ${inches(p.left)} \xB7 Right ${inches(p.right)}`;
|
|
2876
|
+
function Margins({ setup, apply, openDialog }) {
|
|
2877
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Margins", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Scaling, { size: 16 }), testId: "docx-layout-margins", children: (close) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2879
|
+
RibbonGallery,
|
|
2880
|
+
{
|
|
2881
|
+
label: "Margins",
|
|
2882
|
+
current: matchMargins(setup),
|
|
2883
|
+
close,
|
|
2884
|
+
choices: MARGIN_PRESETS.map((p) => ({
|
|
2885
|
+
id: p.id,
|
|
2886
|
+
label: p.label,
|
|
2887
|
+
detail: marginDetail(p)
|
|
2888
|
+
})),
|
|
2889
|
+
onPick: (id) => {
|
|
2890
|
+
const p = MARGIN_PRESETS.find((m) => m.id === id);
|
|
2891
|
+
apply({
|
|
2892
|
+
marginTopTwips: p.top,
|
|
2893
|
+
marginRightTwips: p.right,
|
|
2894
|
+
marginBottomTwips: p.bottom,
|
|
2895
|
+
marginLeftTwips: p.left,
|
|
2896
|
+
scope: "section"
|
|
2897
|
+
});
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
),
|
|
2901
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2902
|
+
"button",
|
|
2903
|
+
{
|
|
2904
|
+
type: "button",
|
|
2905
|
+
className: "native-docx-gallery-more",
|
|
2906
|
+
onClick: () => {
|
|
2907
|
+
close();
|
|
2908
|
+
openDialog();
|
|
2909
|
+
},
|
|
2910
|
+
children: "Custom margins\u2026"
|
|
2911
|
+
}
|
|
2912
|
+
)
|
|
2913
|
+
] }) });
|
|
2914
|
+
}
|
|
2915
|
+
function Orientation({ setup, apply }) {
|
|
2916
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2917
|
+
RibbonMenu,
|
|
2918
|
+
{
|
|
2919
|
+
label: "Orientation",
|
|
2920
|
+
icon: setup?.orientation === "landscape" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RectangleHorizontal, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RectangleVertical, { size: 16 }),
|
|
2921
|
+
testId: "docx-layout-orientation",
|
|
2922
|
+
children: (close) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2923
|
+
RibbonGallery,
|
|
2924
|
+
{
|
|
2925
|
+
label: "Orientation",
|
|
2926
|
+
current: setup?.orientation,
|
|
2927
|
+
close,
|
|
2928
|
+
choices: [
|
|
2929
|
+
{ id: "portrait", label: "Portrait", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RectangleVertical, { size: 16 }) },
|
|
2930
|
+
{ id: "landscape", label: "Landscape", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RectangleHorizontal, { size: 16 }) }
|
|
2931
|
+
],
|
|
2932
|
+
onPick: (id) => apply({ orientation: id, scope: "section" })
|
|
2933
|
+
}
|
|
2934
|
+
)
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
}
|
|
2938
|
+
function Size({ setup, apply, openDialog }) {
|
|
2939
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Size", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { size: 16 }), testId: "docx-layout-size", children: (close) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2940
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2941
|
+
RibbonGallery,
|
|
2942
|
+
{
|
|
2943
|
+
label: "Size",
|
|
2944
|
+
current: matchPaper(setup),
|
|
2945
|
+
close,
|
|
2946
|
+
choices: PAPER_SIZES.map((p) => ({
|
|
2947
|
+
id: p.id,
|
|
2948
|
+
label: p.label,
|
|
2949
|
+
detail: paperDescription(p)
|
|
2950
|
+
})),
|
|
2951
|
+
onPick: (id) => apply({
|
|
2952
|
+
...orientedSize(
|
|
2953
|
+
PAPER_SIZES.find((p) => p.id === id),
|
|
2954
|
+
setup?.orientation
|
|
2955
|
+
),
|
|
2956
|
+
scope: "section"
|
|
2957
|
+
})
|
|
2958
|
+
}
|
|
2959
|
+
),
|
|
2960
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2961
|
+
"button",
|
|
2962
|
+
{
|
|
2963
|
+
type: "button",
|
|
2964
|
+
className: "native-docx-gallery-more",
|
|
2965
|
+
onClick: () => {
|
|
2966
|
+
close();
|
|
2967
|
+
openDialog();
|
|
2968
|
+
},
|
|
2969
|
+
children: "More paper sizes\u2026"
|
|
2970
|
+
}
|
|
2971
|
+
)
|
|
2972
|
+
] }) });
|
|
2973
|
+
}
|
|
2974
|
+
var COLUMN_BREAK = { type: "insertBreak", kind: "column" };
|
|
2975
|
+
function Breaks() {
|
|
2976
|
+
const page = react.useEditorCommand("insert.pageBreak");
|
|
2977
|
+
const nextPage = react.useEditorCommand("insert.sectionBreakNextPage");
|
|
2978
|
+
const continuous = react.useEditorCommand("insert.sectionBreakContinuous");
|
|
2979
|
+
const column = react.useEditorCommand(COLUMN_BREAK);
|
|
2980
|
+
const rows = [
|
|
2981
|
+
{ id: "page", label: "Page", detail: "Start the next page here", command: page },
|
|
2982
|
+
{ id: "column", label: "Column", detail: "Start the next column here", command: column },
|
|
2983
|
+
{
|
|
2984
|
+
id: "nextPage",
|
|
2985
|
+
label: "Next Page",
|
|
2986
|
+
detail: "Section break: new section on the next page",
|
|
2987
|
+
command: nextPage
|
|
2988
|
+
},
|
|
2989
|
+
{
|
|
2990
|
+
id: "continuous",
|
|
2991
|
+
label: "Continuous",
|
|
2992
|
+
detail: "Section break: new section on the same page",
|
|
2993
|
+
command: continuous
|
|
2994
|
+
}
|
|
2995
|
+
];
|
|
2996
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Breaks", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SeparatorHorizontal, { size: 16 }), testId: "docx-layout-breaks", children: (close) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2997
|
+
RibbonGallery,
|
|
2998
|
+
{
|
|
2999
|
+
label: "Breaks",
|
|
3000
|
+
close,
|
|
3001
|
+
choices: rows.map((row) => ({
|
|
3002
|
+
id: row.id,
|
|
3003
|
+
label: row.label,
|
|
3004
|
+
detail: row.detail,
|
|
3005
|
+
disabled: !row.command.isEnabled,
|
|
3006
|
+
title: row.command.disabledReason ?? void 0
|
|
3007
|
+
})),
|
|
3008
|
+
onPick: (id) => void rows.find((row) => row.id === id)?.command.execute()
|
|
3009
|
+
}
|
|
3010
|
+
) });
|
|
3011
|
+
}
|
|
3012
|
+
function LayoutButtons() {
|
|
3013
|
+
const { pageSetup, apply } = react.usePageSetup();
|
|
3014
|
+
const [dialog, setDialog] = React3.useState(false);
|
|
3015
|
+
const props = { setup: pageSetup, apply, openDialog: () => setDialog(true) };
|
|
3016
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3017
|
+
/* @__PURE__ */ jsxRuntime.jsx(Margins, { ...props }),
|
|
3018
|
+
/* @__PURE__ */ jsxRuntime.jsx(Orientation, { ...props }),
|
|
3019
|
+
/* @__PURE__ */ jsxRuntime.jsx(Size, { ...props }),
|
|
3020
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3021
|
+
react.DocxEditor.Toolbar.Action,
|
|
3022
|
+
{
|
|
3023
|
+
label: "Columns",
|
|
3024
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Columns2, { size: 16 }),
|
|
3025
|
+
disabled: true,
|
|
3026
|
+
disabledReason: COLUMNS_UNSUPPORTED,
|
|
3027
|
+
className: "native-docx-layout-columns"
|
|
3028
|
+
}
|
|
3029
|
+
),
|
|
3030
|
+
/* @__PURE__ */ jsxRuntime.jsx(Breaks, {}),
|
|
3031
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3032
|
+
react.DocxEditor.Toolbar.Action,
|
|
3033
|
+
{
|
|
3034
|
+
label: "Page Setup\u2026",
|
|
3035
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { size: 16 }),
|
|
3036
|
+
onSelect: () => setDialog(true),
|
|
3037
|
+
className: "native-docx-layout-page-setup"
|
|
3038
|
+
}
|
|
3039
|
+
),
|
|
3040
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.PageSetupDialog, { open: dialog, onClose: () => setDialog(false) })
|
|
3041
|
+
] });
|
|
3042
|
+
}
|
|
3043
|
+
var ROW_ABOVE = { type: "insertRow", where: "above" };
|
|
3044
|
+
var ROW_BELOW = { type: "insertRow", where: "below" };
|
|
3045
|
+
var COLUMN_LEFT = { type: "insertColumn", where: "left" };
|
|
3046
|
+
var COLUMN_RIGHT = { type: "insertColumn", where: "right" };
|
|
3047
|
+
var MERGE = { type: "mergeCells" };
|
|
3048
|
+
var SPLIT = { type: "splitCell", rows: 1, cols: 2 };
|
|
3049
|
+
var HEADER_ROW = { type: "toggleHeaderRow" };
|
|
3050
|
+
var DELETE_ROW = { type: "deleteRow" };
|
|
3051
|
+
var DELETE_COLUMN = { type: "deleteColumn" };
|
|
3052
|
+
var DELETE_TABLE = { type: "deleteTable" };
|
|
3053
|
+
var ALIGN_TOP = { type: "setTableCellVerticalAlignment", alignment: "top" };
|
|
3054
|
+
var ALIGN_CENTER = { type: "setTableCellVerticalAlignment", alignment: "center" };
|
|
3055
|
+
var ALIGN_BOTTOM = { type: "setTableCellVerticalAlignment", alignment: "bottom" };
|
|
3056
|
+
function useRows(rows) {
|
|
3057
|
+
return rows.map((row) => ({ ...row, state: react.useEditorCommand(row.command) }));
|
|
3058
|
+
}
|
|
3059
|
+
function CommandGallery({
|
|
3060
|
+
label,
|
|
3061
|
+
icon,
|
|
3062
|
+
testId,
|
|
3063
|
+
rows
|
|
3064
|
+
}) {
|
|
3065
|
+
const bound = useRows(rows);
|
|
3066
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3067
|
+
RibbonGallery,
|
|
3068
|
+
{
|
|
3069
|
+
label,
|
|
3070
|
+
close,
|
|
3071
|
+
choices: bound.map((row) => ({
|
|
3072
|
+
id: row.id,
|
|
3073
|
+
label: row.label,
|
|
3074
|
+
icon: row.icon,
|
|
3075
|
+
disabled: !row.state.isEnabled,
|
|
3076
|
+
title: row.state.disabledReason ?? void 0
|
|
3077
|
+
})),
|
|
3078
|
+
onPick: (id) => void bound.find((row) => row.id === id)?.state.execute()
|
|
3079
|
+
}
|
|
3080
|
+
) });
|
|
3081
|
+
}
|
|
3082
|
+
function CommandAction({
|
|
3083
|
+
command,
|
|
3084
|
+
label,
|
|
3085
|
+
icon,
|
|
3086
|
+
testId
|
|
3087
|
+
}) {
|
|
3088
|
+
const state = react.useEditorCommand(command);
|
|
3089
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3090
|
+
react.DocxEditor.Toolbar.Action,
|
|
3091
|
+
{
|
|
3092
|
+
label,
|
|
3093
|
+
icon,
|
|
3094
|
+
active: state.isActive,
|
|
3095
|
+
disabled: !state.isEnabled,
|
|
3096
|
+
disabledReason: state.disabledReason ?? void 0,
|
|
3097
|
+
onSelect: () => void state.execute(),
|
|
3098
|
+
className: `native-docx-table-${testId}`
|
|
3099
|
+
}
|
|
3100
|
+
);
|
|
3101
|
+
}
|
|
3102
|
+
function TableButtons() {
|
|
3103
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3104
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3105
|
+
CommandAction,
|
|
3106
|
+
{
|
|
3107
|
+
command: ROW_ABOVE,
|
|
3108
|
+
label: "Insert row above",
|
|
3109
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BetweenHorizontalStart, { size: 16 }),
|
|
3110
|
+
testId: "row-above"
|
|
3111
|
+
}
|
|
3112
|
+
),
|
|
3113
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3114
|
+
CommandAction,
|
|
3115
|
+
{
|
|
3116
|
+
command: ROW_BELOW,
|
|
3117
|
+
label: "Insert row below",
|
|
3118
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BetweenHorizontalEnd, { size: 16 }),
|
|
3119
|
+
testId: "row-below"
|
|
3120
|
+
}
|
|
3121
|
+
),
|
|
3122
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3123
|
+
CommandAction,
|
|
3124
|
+
{
|
|
3125
|
+
command: COLUMN_LEFT,
|
|
3126
|
+
label: "Insert column left",
|
|
3127
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BetweenVerticalStart, { size: 16 }),
|
|
3128
|
+
testId: "column-left"
|
|
3129
|
+
}
|
|
3130
|
+
),
|
|
3131
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3132
|
+
CommandAction,
|
|
3133
|
+
{
|
|
3134
|
+
command: COLUMN_RIGHT,
|
|
3135
|
+
label: "Insert column right",
|
|
3136
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BetweenVerticalEnd, { size: 16 }),
|
|
3137
|
+
testId: "column-right"
|
|
3138
|
+
}
|
|
3139
|
+
),
|
|
3140
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3141
|
+
CommandGallery,
|
|
3142
|
+
{
|
|
3143
|
+
label: "Delete",
|
|
3144
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 16 }),
|
|
3145
|
+
testId: "docx-table-delete",
|
|
3146
|
+
rows: [
|
|
3147
|
+
{ id: "row", label: "Delete row", command: DELETE_ROW },
|
|
3148
|
+
{ id: "column", label: "Delete column", command: DELETE_COLUMN },
|
|
3149
|
+
{ id: "table", label: "Delete table", command: DELETE_TABLE }
|
|
3150
|
+
]
|
|
3151
|
+
}
|
|
3152
|
+
),
|
|
3153
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3154
|
+
CommandAction,
|
|
3155
|
+
{
|
|
3156
|
+
command: MERGE,
|
|
3157
|
+
label: "Merge cells",
|
|
3158
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Merge, { size: 16 }),
|
|
3159
|
+
testId: "merge"
|
|
3160
|
+
}
|
|
3161
|
+
),
|
|
3162
|
+
/* @__PURE__ */ jsxRuntime.jsx(CommandAction, { command: SPLIT, label: "Split cell", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Split, { size: 16 }), testId: "split" }),
|
|
3163
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3164
|
+
CommandAction,
|
|
3165
|
+
{
|
|
3166
|
+
command: HEADER_ROW,
|
|
3167
|
+
label: "Repeat header row",
|
|
3168
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading, { size: 16 }),
|
|
3169
|
+
testId: "header-row"
|
|
3170
|
+
}
|
|
3171
|
+
),
|
|
3172
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3173
|
+
CommandGallery,
|
|
3174
|
+
{
|
|
3175
|
+
label: "Cell alignment",
|
|
3176
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignVerticalJustifyCenter, { size: 16 }),
|
|
3177
|
+
testId: "docx-table-align",
|
|
3178
|
+
rows: [
|
|
3179
|
+
{
|
|
3180
|
+
id: "top",
|
|
3181
|
+
label: "Top",
|
|
3182
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignVerticalJustifyStart, { size: 16 }),
|
|
3183
|
+
command: ALIGN_TOP
|
|
3184
|
+
},
|
|
3185
|
+
{
|
|
3186
|
+
id: "center",
|
|
3187
|
+
label: "Center",
|
|
3188
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignVerticalJustifyCenter, { size: 16 }),
|
|
3189
|
+
command: ALIGN_CENTER
|
|
3190
|
+
},
|
|
3191
|
+
{
|
|
3192
|
+
id: "bottom",
|
|
3193
|
+
label: "Bottom",
|
|
3194
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignVerticalJustifyEnd, { size: 16 }),
|
|
3195
|
+
command: ALIGN_BOTTOM
|
|
3196
|
+
}
|
|
3197
|
+
]
|
|
3198
|
+
}
|
|
3199
|
+
),
|
|
3200
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderTarget, {}),
|
|
3201
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderStyle, {}),
|
|
3202
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderWidth, {}),
|
|
3203
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderColor, {}),
|
|
3204
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableCellFill, {})
|
|
3205
|
+
] });
|
|
3206
|
+
}
|
|
3207
|
+
var CAPTION_LABELS = ["Figure", "Table", "Equation"];
|
|
3208
|
+
var CAPTION_STYLES = chunkAOFATOT3_cjs.stylesXml(
|
|
3209
|
+
"",
|
|
3210
|
+
'<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style><w:style w:type="paragraph" w:styleId="Caption"><w:name w:val="caption"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:uiPriority w:val="35"/><w:unhideWhenUsed/><w:qFormat/><w:pPr><w:spacing w:after="200" w:line="240" w:lineRule="auto"/></w:pPr><w:rPr><w:i/><w:iCs/><w:color w:val="44546A"/><w:sz w:val="18"/><w:szCs w:val="18"/></w:rPr></w:style>'
|
|
3211
|
+
);
|
|
3212
|
+
function seqIdentifier(instruction) {
|
|
3213
|
+
const match = /^\s*SEQ\s+("[^"]+"|\S+)/i.exec(instruction);
|
|
3214
|
+
return match ? match[1].replace(/"/g, "") : null;
|
|
3215
|
+
}
|
|
3216
|
+
function countSeqFields(root, label, throughId) {
|
|
3217
|
+
let count = 0;
|
|
3218
|
+
let done = false;
|
|
3219
|
+
const target = label.toLowerCase();
|
|
3220
|
+
const visit = (node) => {
|
|
3221
|
+
if (done) return;
|
|
3222
|
+
if (node.localName === "fldSimple") {
|
|
3223
|
+
const instr = node.attributes?.find((a) => a.localName === "instr")?.value ?? "";
|
|
3224
|
+
if (seqIdentifier(instr)?.toLowerCase() === target) count++;
|
|
3225
|
+
} else if (node.localName === "instrText") {
|
|
3226
|
+
const text = (node.children ?? []).map((c) => c.value ?? "").join("");
|
|
3227
|
+
if (seqIdentifier(text)?.toLowerCase() === target) count++;
|
|
3228
|
+
}
|
|
3229
|
+
node.children?.forEach(visit);
|
|
3230
|
+
if (throughId && node.id === throughId) done = true;
|
|
3231
|
+
};
|
|
3232
|
+
visit(root);
|
|
3233
|
+
return count;
|
|
3234
|
+
}
|
|
3235
|
+
function captionParagraphXml(label, number, text) {
|
|
3236
|
+
const run = (value) => `<w:r><w:t xml:space="preserve">${chunkAOFATOT3_cjs.esc(value)}</w:t></w:r>`;
|
|
3237
|
+
const rest = text.trim() ? `: ${text.trim()}` : "";
|
|
3238
|
+
return `<w:p><w:pPr><w:pStyle w:val="Caption"/></w:pPr>${run(`${label} `)}<w:fldSimple w:instr=" SEQ ${chunkAOFATOT3_cjs.esc(label)} \\* ARABIC "><w:r><w:t>${number}</w:t></w:r></w:fldSimple>${rest ? run(rest) : ""}</w:p>`;
|
|
3239
|
+
}
|
|
3240
|
+
function base642(bytes) {
|
|
3241
|
+
let binary = "";
|
|
3242
|
+
for (let i = 0; i < bytes.length; i += 32768)
|
|
3243
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
3244
|
+
return btoa(binary);
|
|
3245
|
+
}
|
|
3246
|
+
function captionFragmentHtml(label, number, text, revision) {
|
|
3247
|
+
const untracked = chunkAOFATOT3_cjs.docxPackage({
|
|
3248
|
+
document: chunkAOFATOT3_cjs.documentXml(captionParagraphXml(label, number, text)),
|
|
3249
|
+
styles: CAPTION_STYLES,
|
|
3250
|
+
title: "Caption"
|
|
3251
|
+
});
|
|
3252
|
+
const bytes = revision ? template.trackInsertion(untracked, revision, true) : untracked;
|
|
3253
|
+
return `<div data-docx-fragment="${base642(bytes)}" data-docx-fragment-end="covered"></div>`;
|
|
3254
|
+
}
|
|
3255
|
+
var TRANSFORMS = Object.fromEntries(
|
|
3256
|
+
["rotateCW", "rotateCCW", "flipH", "flipV"].map((action) => [
|
|
3257
|
+
action,
|
|
3258
|
+
{ type: "transformImage", action }
|
|
3259
|
+
])
|
|
3260
|
+
);
|
|
3261
|
+
function TransformAction({
|
|
3262
|
+
action,
|
|
3263
|
+
label,
|
|
3264
|
+
icon
|
|
3265
|
+
}) {
|
|
3266
|
+
const state = react.useEditorCommand(TRANSFORMS[action]);
|
|
3267
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3268
|
+
react.DocxEditor.Toolbar.Action,
|
|
3269
|
+
{
|
|
3270
|
+
label,
|
|
3271
|
+
icon,
|
|
3272
|
+
disabled: !state.isEnabled,
|
|
3273
|
+
disabledReason: state.disabledReason ?? void 0,
|
|
3274
|
+
onSelect: () => void state.execute(),
|
|
3275
|
+
className: `native-docx-picture-${action}`
|
|
3276
|
+
}
|
|
3277
|
+
);
|
|
3278
|
+
}
|
|
3279
|
+
function insertCaption(editor, label, text, track) {
|
|
3280
|
+
const surface = editor.surface;
|
|
3281
|
+
const selection = surface?.state().selection;
|
|
3282
|
+
if (!surface || !selection) return null;
|
|
3283
|
+
const { paragraphId } = selection.head;
|
|
3284
|
+
const number = countSeqFields(
|
|
3285
|
+
surface.session.part().root,
|
|
3286
|
+
label,
|
|
3287
|
+
paragraphId
|
|
3288
|
+
) + 1;
|
|
3289
|
+
const ids = surface.session.paragraphIds();
|
|
3290
|
+
const next = ids[ids.indexOf(paragraphId) + 1];
|
|
3291
|
+
const caption = `${label} ${number}${text.trim() ? `: ${text.trim()}` : ""}`;
|
|
3292
|
+
const outcome = track({
|
|
3293
|
+
label: `Inserted caption: ${caption}`,
|
|
3294
|
+
inserted: (inserted) => inserted !== null,
|
|
3295
|
+
insert: (revision) => {
|
|
3296
|
+
if (next) {
|
|
3297
|
+
surface.setSelection({
|
|
3298
|
+
anchor: { paragraphId: next, offset: 0 },
|
|
3299
|
+
head: { paragraphId: next, offset: 0 }
|
|
3300
|
+
});
|
|
3301
|
+
} else {
|
|
3302
|
+
editor.exec({ type: "selectAll" });
|
|
3303
|
+
const end = surface.state().selection?.head;
|
|
3304
|
+
if (!end) return null;
|
|
3305
|
+
surface.setSelection({ anchor: end, head: end });
|
|
3306
|
+
surface.splitParagraph();
|
|
3307
|
+
}
|
|
3308
|
+
const ok2 = editor.exec({
|
|
3309
|
+
type: "paste",
|
|
3310
|
+
text: caption,
|
|
3311
|
+
html: captionFragmentHtml(label, number, text, revision)
|
|
3312
|
+
}).ok;
|
|
3313
|
+
return ok2 ? number : null;
|
|
3314
|
+
}
|
|
3315
|
+
});
|
|
3316
|
+
return outcome?.result ?? null;
|
|
3317
|
+
}
|
|
3318
|
+
function CaptionButton({ defaultLabel = "Figure" }) {
|
|
3319
|
+
const editor = react.useDocxEditor();
|
|
3320
|
+
const track = useTrackedOrNoted();
|
|
3321
|
+
const [label, setLabel] = React3.useState(defaultLabel);
|
|
3322
|
+
const [text, setText] = React3.useState("");
|
|
3323
|
+
const [error, setError] = React3.useState("");
|
|
3324
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Insert caption", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Captions, { size: 16 }), testId: "docx-insert-caption", children: (close) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3325
|
+
"form",
|
|
3326
|
+
{
|
|
3327
|
+
className: "native-docx-form",
|
|
3328
|
+
onSubmit: (event) => {
|
|
3329
|
+
event.preventDefault();
|
|
3330
|
+
if (!editor) return;
|
|
3331
|
+
try {
|
|
3332
|
+
if (insertCaption(editor, label, text, track) === null)
|
|
3333
|
+
return setError("The caption could not be inserted here.");
|
|
3334
|
+
setText("");
|
|
3335
|
+
setError("");
|
|
3336
|
+
close();
|
|
3337
|
+
editor.focus();
|
|
3338
|
+
} catch (failure) {
|
|
3339
|
+
setError(failure instanceof Error ? failure.message : String(failure));
|
|
3340
|
+
}
|
|
3341
|
+
},
|
|
3342
|
+
children: [
|
|
3343
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
3344
|
+
"Label",
|
|
3345
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3346
|
+
"select",
|
|
3347
|
+
{
|
|
3348
|
+
value: label,
|
|
3349
|
+
onChange: (event) => setLabel(event.target.value),
|
|
3350
|
+
children: CAPTION_LABELS.map((value) => /* @__PURE__ */ jsxRuntime.jsx("option", { children: value }, value))
|
|
3351
|
+
}
|
|
3352
|
+
)
|
|
3353
|
+
] }),
|
|
3354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
3355
|
+
"Caption",
|
|
3356
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3357
|
+
"input",
|
|
3358
|
+
{
|
|
3359
|
+
autoFocus: true,
|
|
3360
|
+
value: text,
|
|
3361
|
+
placeholder: "Optional text after the number",
|
|
3362
|
+
"data-testid": "docx-caption-text",
|
|
3363
|
+
onChange: (event) => setText(event.target.value)
|
|
3364
|
+
}
|
|
3365
|
+
)
|
|
3366
|
+
] }),
|
|
3367
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", children: error }),
|
|
3368
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", "data-testid": "docx-caption-insert", children: "Insert" })
|
|
3369
|
+
]
|
|
3370
|
+
}
|
|
3371
|
+
) });
|
|
3372
|
+
}
|
|
3373
|
+
function PictureButtons() {
|
|
3374
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3375
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageWrap, {}),
|
|
3376
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageProperties, {}),
|
|
3377
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageAltText, {}),
|
|
3378
|
+
/* @__PURE__ */ jsxRuntime.jsx(TransformAction, { action: "rotateCW", label: "Rotate right 90\xB0", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCw, { size: 16 }) }),
|
|
3379
|
+
/* @__PURE__ */ jsxRuntime.jsx(TransformAction, { action: "rotateCCW", label: "Rotate left 90\xB0", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { size: 16 }) }),
|
|
3380
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3381
|
+
TransformAction,
|
|
3382
|
+
{
|
|
3383
|
+
action: "flipH",
|
|
3384
|
+
label: "Flip horizontal",
|
|
3385
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlipHorizontal2, { size: 16 })
|
|
3386
|
+
}
|
|
3387
|
+
),
|
|
3388
|
+
/* @__PURE__ */ jsxRuntime.jsx(TransformAction, { action: "flipV", label: "Flip vertical", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlipVertical2, { size: 16 }) }),
|
|
3389
|
+
/* @__PURE__ */ jsxRuntime.jsx(CaptionButton, {})
|
|
3390
|
+
] });
|
|
3391
|
+
}
|
|
3392
|
+
var LAYOUT_TAB = "Layout";
|
|
3393
|
+
var TABLE_TAB = "Table";
|
|
3394
|
+
var PICTURE_TAB = "Picture";
|
|
3395
|
+
function useContextualTabs(tab) {
|
|
3396
|
+
const inTable = react.useEditorState((snapshot) => snapshot.table !== null);
|
|
3397
|
+
const onPicture = react.useEditorState((snapshot) => snapshot.image !== null);
|
|
3398
|
+
const tabs = [...inTable ? [TABLE_TAB] : [], ...onPicture ? [PICTURE_TAB] : []];
|
|
3399
|
+
const contextual = tab === TABLE_TAB || tab === PICTURE_TAB;
|
|
3400
|
+
return { tabs, shown: contextual && !tabs.includes(tab) ? "Home" : tab };
|
|
3401
|
+
}
|
|
3402
|
+
function LayoutTabContent({ tab }) {
|
|
3403
|
+
if (tab === LAYOUT_TAB) return /* @__PURE__ */ jsxRuntime.jsx(LayoutButtons, {});
|
|
3404
|
+
if (tab === TABLE_TAB) return /* @__PURE__ */ jsxRuntime.jsx(TableButtons, {});
|
|
3405
|
+
if (tab === PICTURE_TAB) return /* @__PURE__ */ jsxRuntime.jsx(PictureButtons, {});
|
|
3406
|
+
return null;
|
|
3407
|
+
}
|
|
3408
|
+
var contains = (node, id) => node.id === id || (node.children ?? []).some((child) => contains(child, id));
|
|
3409
|
+
function firstParagraph(node) {
|
|
3410
|
+
for (const child of node.children ?? []) {
|
|
3411
|
+
if (child.kind === "paragraph" && child.id) return child.id;
|
|
3412
|
+
if (child.localName === "tbl") continue;
|
|
3413
|
+
const nested = firstParagraph(child);
|
|
3414
|
+
if (nested) return nested;
|
|
3415
|
+
}
|
|
3416
|
+
return null;
|
|
3417
|
+
}
|
|
3418
|
+
function tableCells(root, paragraphId) {
|
|
3419
|
+
let table = null;
|
|
3420
|
+
const find = (node) => {
|
|
3421
|
+
if (node.localName === "tbl" && contains(node, paragraphId)) table = node;
|
|
3422
|
+
for (const child of node.children ?? []) if (contains(child, paragraphId)) find(child);
|
|
3423
|
+
};
|
|
3424
|
+
find(root);
|
|
3425
|
+
if (!table) return null;
|
|
3426
|
+
const cells = [];
|
|
3427
|
+
let index = -1;
|
|
3428
|
+
const rows = (node) => (node.children ?? []).flatMap(
|
|
3429
|
+
(child) => child.localName === "tr" ? [child] : child.localName === "tbl" ? [] : rows(child)
|
|
3430
|
+
);
|
|
3431
|
+
for (const row of rows(table))
|
|
3432
|
+
for (const cell of (row.children ?? []).filter((child) => child.localName === "tc")) {
|
|
3433
|
+
const first = firstParagraph(cell);
|
|
3434
|
+
if (!first) continue;
|
|
3435
|
+
if (contains(cell, paragraphId)) index = cells.length;
|
|
3436
|
+
cells.push(first);
|
|
3437
|
+
}
|
|
3438
|
+
return index < 0 ? null : { cells, index };
|
|
3439
|
+
}
|
|
3440
|
+
function TableTabKeys({ scope }) {
|
|
3441
|
+
const editor = react.useDocxEditor();
|
|
3442
|
+
const latest = React3.useRef(editor);
|
|
3443
|
+
latest.current = editor;
|
|
3444
|
+
React3.useEffect(() => {
|
|
3445
|
+
const element = scope.current;
|
|
3446
|
+
if (!element) return;
|
|
3447
|
+
const onKeyDown = (event) => {
|
|
3448
|
+
if (event.key !== "Tab" || event.ctrlKey || event.metaKey || event.altKey) return;
|
|
3449
|
+
const editor2 = latest.current;
|
|
3450
|
+
const surface = editor2?.surface;
|
|
3451
|
+
const head = surface?.state().selection?.head;
|
|
3452
|
+
if (!editor2 || !surface || !head) return;
|
|
3453
|
+
const root = () => surface.session.part().root;
|
|
3454
|
+
const table = tableCells(root(), head.paragraphId);
|
|
3455
|
+
if (!table) return;
|
|
3456
|
+
event.preventDefault();
|
|
3457
|
+
event.stopPropagation();
|
|
3458
|
+
let target = table.cells[table.index + (event.shiftKey ? -1 : 1)];
|
|
3459
|
+
if (!target && !event.shiftKey && editor2.exec({ type: "insertRow", where: "below" }).ok) {
|
|
3460
|
+
const grown = tableCells(
|
|
3461
|
+
root(),
|
|
3462
|
+
surface.state().selection?.head.paragraphId ?? head.paragraphId
|
|
3463
|
+
);
|
|
3464
|
+
target = grown?.cells[table.cells.length] ?? "";
|
|
3465
|
+
}
|
|
3466
|
+
if (!target) return;
|
|
3467
|
+
const point = { paragraphId: target, offset: 0 };
|
|
3468
|
+
surface.setSelection({ anchor: point, head: point });
|
|
3469
|
+
};
|
|
3470
|
+
element.addEventListener("keydown", onKeyDown, true);
|
|
3471
|
+
return () => element.removeEventListener("keydown", onKeyDown, true);
|
|
3472
|
+
}, [scope]);
|
|
3473
|
+
return null;
|
|
3474
|
+
}
|
|
2789
3475
|
function QuickParts() {
|
|
2790
3476
|
const house = useHouseTemplate();
|
|
2791
3477
|
if (!house || house.blocks.length === 0) return null;
|
|
@@ -2925,48 +3611,39 @@ function DocxParticipants({ session }) {
|
|
|
2925
3611
|
function DefinedTermButtons() {
|
|
2926
3612
|
const terms = useDefinedTerms();
|
|
2927
3613
|
if (!terms) return null;
|
|
2928
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
),
|
|
2942
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2943
|
-
"button",
|
|
2944
|
-
{
|
|
2945
|
-
type: "button",
|
|
2946
|
-
className: "native-docx-ribbon-trigger",
|
|
2947
|
-
"aria-label": terms.labels.update,
|
|
2948
|
-
title: terms.labels.update,
|
|
2949
|
-
"data-testid": "docx-update-definitions",
|
|
2950
|
-
onMouseDown: (event) => event.preventDefault(),
|
|
2951
|
-
onClick: () => terms.update(),
|
|
2952
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListRestart, { size: 16 })
|
|
2953
|
-
}
|
|
2954
|
-
)
|
|
2955
|
-
] });
|
|
3614
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3615
|
+
"button",
|
|
3616
|
+
{
|
|
3617
|
+
type: "button",
|
|
3618
|
+
className: "native-docx-ribbon-trigger",
|
|
3619
|
+
"aria-label": terms.labels.insert,
|
|
3620
|
+
title: `${terms.labels.insert} (type @@)`,
|
|
3621
|
+
"data-testid": "docx-insert-defined-term",
|
|
3622
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
3623
|
+
onClick: (event) => terms.openPicker(event.currentTarget),
|
|
3624
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookA, { size: 16 })
|
|
3625
|
+
}
|
|
3626
|
+
);
|
|
2956
3627
|
}
|
|
2957
3628
|
function DocxRibbon({
|
|
2958
3629
|
onSave,
|
|
2959
|
-
badge
|
|
3630
|
+
badge,
|
|
3631
|
+
imageGeneration
|
|
2960
3632
|
}) {
|
|
2961
|
-
const [
|
|
3633
|
+
const [selected, setTab] = React3.useState("Home");
|
|
3634
|
+
const contextual = useContextualTabs(selected);
|
|
3635
|
+
useGenerateImageTarget();
|
|
3636
|
+
const tab = contextual.shown;
|
|
2962
3637
|
const t = react.useChromeTranslate();
|
|
2963
3638
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-ribbon", children: [
|
|
2964
3639
|
/* @__PURE__ */ jsxRuntime.jsxs("select", { "aria-label": "Ribbon tab", value: tab, onChange: (event) => setTab(event.target.value), children: [
|
|
2965
3640
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Home" }),
|
|
2966
3641
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Insert" }),
|
|
2967
3642
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Design" }),
|
|
3643
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { children: LAYOUT_TAB }),
|
|
2968
3644
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "References" }),
|
|
2969
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Review" })
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Review" }),
|
|
3646
|
+
contextual.tabs.map((name) => /* @__PURE__ */ jsxRuntime.jsx("option", { children: name }, name))
|
|
2970
3647
|
] }),
|
|
2971
3648
|
/* @__PURE__ */ jsxRuntime.jsxs(react.DocxEditor.Toolbar, { t, preset: false, onSave, children: [
|
|
2972
3649
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Undo, {}),
|
|
@@ -2997,10 +3674,14 @@ function DocxRibbon({
|
|
|
2997
3674
|
tab === "Insert" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2998
3675
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableInsert, {}),
|
|
2999
3676
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageInsert, {}),
|
|
3677
|
+
imageGeneration && /* @__PURE__ */ jsxRuntime.jsx(GenerateImageButton, { generation: imageGeneration }),
|
|
3678
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Button, { slotId: "insert.pageBreak" }),
|
|
3000
3679
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Link, {}),
|
|
3001
3680
|
/* @__PURE__ */ jsxRuntime.jsx(DefinedTermButtons, {}),
|
|
3002
3681
|
/* @__PURE__ */ jsxRuntime.jsx(QuickParts, {})
|
|
3003
3682
|
] }),
|
|
3683
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableCellFill, { hidden: true }),
|
|
3684
|
+
/* @__PURE__ */ jsxRuntime.jsx(LayoutTabContent, { tab }),
|
|
3004
3685
|
tab === "Design" && /* @__PURE__ */ jsxRuntime.jsx(HouseTemplatePanel, {}),
|
|
3005
3686
|
tab === "References" && /* @__PURE__ */ jsxRuntime.jsx(NoteButtons, {}),
|
|
3006
3687
|
tab === "Review" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -3376,6 +4057,10 @@ function NativeDocxEditor({
|
|
|
3376
4057
|
DocxRibbon,
|
|
3377
4058
|
{
|
|
3378
4059
|
onSave: () => void saveVersion(),
|
|
4060
|
+
imageGeneration: adapter.imageGeneration && {
|
|
4061
|
+
notify: adapter.notify,
|
|
4062
|
+
...adapter.imageGeneration
|
|
4063
|
+
},
|
|
3379
4064
|
badge: (
|
|
3380
4065
|
// Says the document is shared live, in place of a title row above the ribbon.
|
|
3381
4066
|
ready.room && ready.canEdit && !snapshot ? /* @__PURE__ */ jsxRuntime.jsx("span", { title: "Edits sync live with everyone who has this document open", children: "Co-edit mode" }) : void 0
|
|
@@ -3383,6 +4068,7 @@ function NativeDocxEditor({
|
|
|
3383
4068
|
}
|
|
3384
4069
|
),
|
|
3385
4070
|
!stream && /* @__PURE__ */ jsxRuntime.jsx(WordShortcuts, { scope: stageRef }),
|
|
4071
|
+
!stream && /* @__PURE__ */ jsxRuntime.jsx(TableTabKeys, { scope: stageRef }),
|
|
3386
4072
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3387
4073
|
"div",
|
|
3388
4074
|
{
|
|
@@ -3525,6 +4211,7 @@ exports.DocxEditorReview = DocxEditorReview;
|
|
|
3525
4211
|
exports.DocxMentions = DocxMentions;
|
|
3526
4212
|
exports.DocxParticipants = DocxParticipants;
|
|
3527
4213
|
exports.DocxRibbon = DocxRibbon;
|
|
4214
|
+
exports.GenerateImageButton = GenerateImageButton;
|
|
3528
4215
|
exports.HouseTemplateProvider = HouseTemplateProvider;
|
|
3529
4216
|
exports.NativeDocxEditor = NativeDocxEditor;
|
|
3530
4217
|
exports.builtinHouseTemplate = builtinHouseTemplate;
|
|
@@ -3539,12 +4226,11 @@ exports.reviewModule = reviewModule;
|
|
|
3539
4226
|
exports.structuralPort = structuralPort;
|
|
3540
4227
|
exports.templateFileName = templateFileName;
|
|
3541
4228
|
exports.trackedOrNoted = trackedOrNoted;
|
|
3542
|
-
exports.updateDefinitions = updateDefinitions;
|
|
3543
4229
|
exports.useDefinedTerms = useDefinedTerms;
|
|
3544
4230
|
exports.useHouseTemplate = useHouseTemplate;
|
|
3545
4231
|
exports.useReview = useReview;
|
|
3546
4232
|
exports.useReviewItem = useReviewItem;
|
|
3547
4233
|
exports.useTrackedOrNoted = useTrackedOrNoted;
|
|
3548
4234
|
exports.withDirectEditing = withDirectEditing;
|
|
3549
|
-
//# sourceMappingURL=chunk-
|
|
3550
|
-
//# sourceMappingURL=chunk-
|
|
4235
|
+
//# sourceMappingURL=chunk-FAGQTB3D.cjs.map
|
|
4236
|
+
//# sourceMappingURL=chunk-FAGQTB3D.cjs.map
|