@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.
Files changed (84) hide show
  1. package/dist/agents/index.cjs +207 -207
  2. package/dist/agents/index.js +2 -2
  3. package/dist/{chunk-AOFATOT3.cjs → chunk-2A4MDHJR.cjs} +7 -5
  4. package/dist/chunk-2A4MDHJR.cjs.map +1 -0
  5. package/dist/{chunk-G5JH2YMQ.js → chunk-4GFB5U3K.js} +3 -3
  6. package/dist/{chunk-G5JH2YMQ.js.map → chunk-4GFB5U3K.js.map} +1 -1
  7. package/dist/chunk-5FYU7ZIU.cjs +139 -0
  8. package/dist/chunk-5FYU7ZIU.cjs.map +1 -0
  9. package/dist/{chunk-Y5XW57U4.cjs → chunk-7LLLQUM7.cjs} +5 -5
  10. package/dist/{chunk-Y5XW57U4.cjs.map → chunk-7LLLQUM7.cjs.map} +1 -1
  11. package/dist/{chunk-D3QPYKZG.js → chunk-EPHGD4YV.js} +7 -6
  12. package/dist/chunk-EPHGD4YV.js.map +1 -0
  13. package/dist/chunk-HFZ45FD3.js +133 -0
  14. package/dist/chunk-HFZ45FD3.js.map +1 -0
  15. package/dist/{chunk-5NQIBJPP.js → chunk-NJX774HB.js} +3 -3
  16. package/dist/{chunk-5NQIBJPP.js.map → chunk-NJX774HB.js.map} +1 -1
  17. package/dist/{chunk-DDYXFALG.cjs → chunk-NW3LFDZL.cjs} +3 -3
  18. package/dist/{chunk-DDYXFALG.cjs.map → chunk-NW3LFDZL.cjs.map} +1 -1
  19. package/dist/{chunk-YGREW5TZ.js → chunk-PIT2YZCK.js} +3 -3
  20. package/dist/{chunk-YGREW5TZ.js.map → chunk-PIT2YZCK.js.map} +1 -1
  21. package/dist/{chunk-Z3G65XHZ.js → chunk-S55VDTX3.js} +3 -3
  22. package/dist/{chunk-Z3G65XHZ.js.map → chunk-S55VDTX3.js.map} +1 -1
  23. package/dist/{chunk-LENXDIMY.cjs → chunk-SKSE4OT6.cjs} +22 -22
  24. package/dist/{chunk-LENXDIMY.cjs.map → chunk-SKSE4OT6.cjs.map} +1 -1
  25. package/dist/{chunk-ZT2EBBSC.cjs → chunk-TP3FAP5J.cjs} +5 -5
  26. package/dist/{chunk-ZT2EBBSC.cjs.map → chunk-TP3FAP5J.cjs.map} +1 -1
  27. package/dist/{chunk-MYALCKDR.js → chunk-W2RTZOK3.js} +1533 -263
  28. package/dist/chunk-W2RTZOK3.js.map +1 -0
  29. package/dist/{chunk-FAGQTB3D.cjs → chunk-ZWWN4CUL.cjs} +1690 -408
  30. package/dist/chunk-ZWWN4CUL.cjs.map +1 -0
  31. package/dist/connect/docx.cjs +8 -7
  32. package/dist/connect/docx.cjs.map +1 -1
  33. package/dist/connect/docx.js +6 -5
  34. package/dist/connect/docx.js.map +1 -1
  35. package/dist/connect/index.cjs +12 -11
  36. package/dist/connect/index.cjs.map +1 -1
  37. package/dist/connect/index.js +5 -4
  38. package/dist/connect/index.js.map +1 -1
  39. package/dist/docx/LinkHoverCard.d.ts +24 -0
  40. package/dist/docx/NativeDocxEditor.d.ts +6 -0
  41. package/dist/docx/RibbonMenu.d.ts +4 -1
  42. package/dist/docx/RibbonOverflow.d.ts +27 -0
  43. package/dist/docx/WordReferences.d.ts +3 -2
  44. package/dist/docx/beforeSave.d.ts +9 -0
  45. package/dist/docx/definitions/fragment.d.ts +19 -1
  46. package/dist/docx/definitions/port.d.ts +43 -11
  47. package/dist/docx/index.cjs +85 -36
  48. package/dist/docx/index.cjs.map +1 -1
  49. package/dist/docx/index.d.ts +6 -0
  50. package/dist/docx/index.js +5 -4
  51. package/dist/docx/index.js.map +1 -1
  52. package/dist/docx/noteStyles.d.ts +46 -0
  53. package/dist/docx/overflowPlan.d.ts +15 -0
  54. package/dist/docx/references/CrossReferences.d.ts +97 -0
  55. package/dist/docx/references/EditorMenus.d.ts +10 -0
  56. package/dist/docx/references/commands.d.ts +119 -0
  57. package/dist/docx/references/numbering.d.ts +49 -0
  58. package/dist/docx/references/passages.d.ts +32 -0
  59. package/dist/docx/references/port.d.ts +20 -0
  60. package/dist/facts/index.cjs +22 -129
  61. package/dist/facts/index.cjs.map +1 -1
  62. package/dist/facts/index.js +3 -125
  63. package/dist/facts/index.js.map +1 -1
  64. package/dist/files/index.cjs +1 -1
  65. package/dist/files/index.js +1 -1
  66. package/dist/home/index.cjs +1 -1
  67. package/dist/home/index.js +1 -1
  68. package/dist/index.cjs +314 -314
  69. package/dist/index.js +8 -8
  70. package/dist/shell/index.cjs +1 -1
  71. package/dist/shell/index.js +1 -1
  72. package/dist/studio/index.cjs +1 -1
  73. package/dist/studio/index.js +1 -1
  74. package/dist/tags/ooxml.d.ts +4 -0
  75. package/dist/workflow-canvas/index.cjs +9 -9
  76. package/dist/workflow-canvas/index.js +2 -2
  77. package/node_modules/@arbidocs/coedit/package.json +1 -1
  78. package/package.json +4 -4
  79. package/src/docx/README.md +32 -0
  80. package/src/docx/styles.css +73 -5
  81. package/dist/chunk-AOFATOT3.cjs.map +0 -1
  82. package/dist/chunk-D3QPYKZG.js.map +0 -1
  83. package/dist/chunk-FAGQTB3D.cjs.map +0 -1
  84. package/dist/chunk-MYALCKDR.js.map +0 -1
@@ -1,17 +1,19 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkAOFATOT3_cjs = require('./chunk-AOFATOT3.cjs');
4
+ var chunk5FYU7ZIU_cjs = require('./chunk-5FYU7ZIU.cjs');
5
+ var chunk2A4MDHJR_cjs = require('./chunk-2A4MDHJR.cjs');
5
6
  var chunk7UTB4PHM_cjs = require('./chunk-7UTB4PHM.cjs');
6
7
  var fflate = require('fflate');
7
8
  var store = require('@docx-editor.dev/core/store');
8
- var React3 = require('react');
9
+ var React4 = require('react');
9
10
  var react = require('@docx-editor.dev/react');
10
11
  var ui = require('@arbidocs/react/ui');
11
12
  var lucideReact = require('lucide-react');
12
13
  var jsxRuntime = require('react/jsx-runtime');
13
14
  var reactDom = require('react-dom');
14
15
  var template = require('@arbidocs/coedit/template');
16
+ var layout = require('@docx-editor.dev/core/layout');
15
17
  var editor = require('@docx-editor.dev/core/editor');
16
18
  var server = require('react-dom/server');
17
19
  var Y = require('yjs');
@@ -38,7 +40,7 @@ function _interopNamespace(e) {
38
40
  return Object.freeze(n);
39
41
  }
40
42
 
41
- var React3__default = /*#__PURE__*/_interopDefault(React3);
43
+ var React4__default = /*#__PURE__*/_interopDefault(React4);
42
44
  var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
43
45
 
44
46
  function normalizeDocxExport(data) {
@@ -134,10 +136,10 @@ function useReview() {
134
136
  const editor = react.useDocxEditor();
135
137
  const version = react.useEditorSnapshot(editor);
136
138
  const revision = editor?.getReviewRevision() ?? 0;
137
- const items = React3.useMemo(() => editor ? editor.getReviewItems() : NONE, [editor, revision]);
139
+ const items = React4.useMemo(() => editor ? editor.getReviewItems() : NONE, [editor, revision]);
138
140
  const paneOpen = editor?.isReviewPaneOpen() ?? false;
139
141
  const activeKey = items.find((item) => item.isActive)?.key ?? null;
140
- return React3.useMemo(
142
+ return React4.useMemo(
141
143
  () => ({
142
144
  ready: editor !== null,
143
145
  items,
@@ -159,9 +161,9 @@ function useReview() {
159
161
  [editor, items, activeKey, paneOpen, version]
160
162
  );
161
163
  }
162
- var ReviewItemContext = React3.createContext(null);
164
+ var ReviewItemContext = React4.createContext(null);
163
165
  function useReviewItem() {
164
- return React3.useContext(ReviewItemContext);
166
+ return React4.useContext(ReviewItemContext);
165
167
  }
166
168
 
167
169
  // src/docx/review/commentText.ts
@@ -287,7 +289,7 @@ function ReplyForm({
287
289
  review,
288
290
  onDismiss
289
291
  }) {
290
- const [text, setText] = React3.useState("");
292
+ const [text, setText] = React4.useState("");
291
293
  return /* @__PURE__ */ jsxRuntime.jsxs(
292
294
  "form",
293
295
  {
@@ -458,9 +460,9 @@ function Draft({
458
460
  onCancel,
459
461
  formRef
460
462
  }) {
461
- const [text, setText] = React3.useState("");
462
- const input = React3.useRef(null);
463
- React3.useEffect(() => input.current?.focus(), []);
463
+ const [text, setText] = React4.useState("");
464
+ const input = React4.useRef(null);
465
+ React4.useEffect(() => input.current?.focus(), []);
464
466
  return /* @__PURE__ */ jsxRuntime.jsxs(
465
467
  "form",
466
468
  {
@@ -510,11 +512,11 @@ function Draft({
510
512
  );
511
513
  }
512
514
  function useScrollArea(anchor, ready) {
513
- const [area, setArea] = React3.useState({
515
+ const [area, setArea] = React4.useState({
514
516
  element: null,
515
517
  width: 0
516
518
  });
517
- React3.useLayoutEffect(() => {
519
+ React4.useLayoutEffect(() => {
518
520
  const element = anchor.current?.closest(".docx-editor__scroll-container") ?? null;
519
521
  const measure = () => setArea(
520
522
  (previous) => previous.element === element && previous.width === (element?.clientWidth ?? 0) ? previous : { element, width: element?.clientWidth ?? 0 }
@@ -531,26 +533,26 @@ function DocxEditorReviewRail({
531
533
  children
532
534
  }) {
533
535
  const editor = react.useDocxEditor();
534
- const registry = React3.useContext(react.ReviewRailContext);
536
+ const registry = React4.useContext(react.ReviewRailContext);
535
537
  const review = useReview();
536
- const [draft, setDraft] = React3.useState(null);
537
- const [tops, setTops] = React3.useState({});
538
- const [showResolved, setShowResolved] = React3.useState(true);
539
- const elements = React3.useRef(/* @__PURE__ */ new Map());
540
- const anchor = React3.useRef(null);
541
- const toolbar = React3.useRef(null);
538
+ const [draft, setDraft] = React4.useState(null);
539
+ const [tops, setTops] = React4.useState({});
540
+ const [showResolved, setShowResolved] = React4.useState(true);
541
+ const elements = React4.useRef(/* @__PURE__ */ new Map());
542
+ const anchor = React4.useRef(null);
543
+ const toolbar = React4.useRef(null);
542
544
  const area = useScrollArea(anchor, review.ready);
543
545
  const layout = area.width === 0 || area.width >= REVIEW_MARGIN_MIN_WIDTH ? "margin" : "compact";
544
- const openDraft = React3.useCallback(() => {
546
+ const openDraft = React4.useCallback(() => {
545
547
  const placement = editor?.getSelectionPlacement();
546
548
  if (!placement) return;
547
549
  review.setPaneOpen(true);
548
550
  setDraft({ anchorY: placement.anchorY });
549
551
  }, [editor, review.setPaneOpen]);
550
- React3.useEffect(() => registry?.register(), [registry]);
551
- React3.useEffect(() => registry?.registerCommentDraft(openDraft), [registry, openDraft]);
552
- const shownLayout = React3.useRef(null);
553
- React3.useEffect(() => {
552
+ React4.useEffect(() => registry?.register(), [registry]);
553
+ React4.useEffect(() => registry?.registerCommentDraft(openDraft), [registry, openDraft]);
554
+ const shownLayout = React4.useRef(null);
555
+ React4.useEffect(() => {
554
556
  if (!review.ready || area.width === 0 || shownLayout.current === layout) return;
555
557
  editor?.setReviewPaneOptions({ opening: layout === "margin" ? "auto" : "manual" });
556
558
  const deepLinked = shownLayout.current === null && review.activeKey !== null;
@@ -566,7 +568,7 @@ function DocxEditorReviewRail({
566
568
  const changes = review.items.filter((entry) => entry.kind === "revision").length;
567
569
  const comments = top.filter((entry) => entry.kind === "comment").length;
568
570
  const hasResolved = review.items.some((entry) => entry.kind === "comment" && entry.resolved);
569
- const repliesOf = React3.useCallback(
571
+ const repliesOf = React4.useCallback(
570
572
  (entry) => review.items.filter(
571
573
  (other) => other.kind === "comment" && (other.parentId === entry.id || other.parentRevisionId === entry.id)
572
574
  ),
@@ -574,19 +576,19 @@ function DocxEditorReviewRail({
574
576
  );
575
577
  const column = layout === "margin" && review.paneOpen && (top.length > 0 || draft !== null);
576
578
  const bubbleOpen = layout === "compact" && (review.paneOpen || draft !== null);
577
- React3.useEffect(() => {
579
+ React4.useEffect(() => {
578
580
  const element = area.element;
579
581
  if (!element) return;
580
582
  if (column) element.setAttribute("data-review-margin", "");
581
583
  else element.removeAttribute("data-review-margin");
582
584
  return () => element.removeAttribute("data-review-margin");
583
585
  }, [area.element, column]);
584
- const dismiss = React3.useCallback(() => {
586
+ const dismiss = React4.useCallback(() => {
585
587
  setDraft(null);
586
588
  if (layout === "compact") review.setPaneOpen(false);
587
589
  else review.setActive(null);
588
590
  }, [layout, review.setPaneOpen, review.setActive]);
589
- React3.useEffect(() => {
591
+ React4.useEffect(() => {
590
592
  const element = area.element;
591
593
  if (!element || !bubbleOpen) return;
592
594
  const close = (event) => {
@@ -611,7 +613,7 @@ function DocxEditorReviewRail({
611
613
  document2.removeEventListener("keydown", escape);
612
614
  };
613
615
  }, [area.element, bubbleOpen, dismiss]);
614
- React3.useLayoutEffect(() => {
616
+ React4.useLayoutEffect(() => {
615
617
  if (!column) return;
616
618
  const next = {};
617
619
  let floor = (toolbar.current?.offsetHeight ?? 0) + CARD_GAP;
@@ -910,18 +912,18 @@ function mentionCandidates(mentions) {
910
912
  function mentionedDocxRecipients(text, mentions) {
911
913
  return chunk7UTB4PHM_cjs.extractMentions(text, mentionCandidates(mentions)).map((person) => person.id);
912
914
  }
913
- var ActivityContext = React3.createContext({});
915
+ var ActivityContext = React4.createContext({});
914
916
  function DocxCommentActivity() {
915
917
  const item = useReviewItem();
916
918
  const review = useReview();
917
- const activity = React3.useContext(ActivityContext);
918
- const [reading, setReading] = React3.useState(false);
919
+ const activity = React4.useContext(ActivityContext);
920
+ const [reading, setReading] = React4.useState(false);
919
921
  if (!item || item.kind !== "comment") return null;
920
922
  const commentId = item.parentId || item.item.id;
921
923
  const thread = review.items.filter(
922
924
  (entry) => entry.kind === "comment" && (entry.item.id === commentId || entry.parentId === commentId)
923
925
  );
924
- const statuses = Object.entries(activity).filter(([, run]) => run.commentId === commentId);
926
+ const statuses = Object.entries(activity).filter(([, run2]) => run2.commentId === commentId);
925
927
  const labels = {
926
928
  delivering: "Delivering mention\u2026",
927
929
  queued: "Queued\u2026",
@@ -933,18 +935,18 @@ function DocxCommentActivity() {
933
935
  unknown: "Status unavailable"
934
936
  };
935
937
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-comment-extra", "data-review-selectable": "", children: [
936
- statuses.map(([id, run]) => /* @__PURE__ */ jsxRuntime.jsxs(
938
+ statuses.map(([id, run2]) => /* @__PURE__ */ jsxRuntime.jsxs(
937
939
  "div",
938
940
  {
939
941
  role: "status",
940
942
  "data-testid": "docx-comment-agent-status",
941
- "data-status": run.status,
943
+ "data-status": run2.status,
942
944
  className: "native-docx-comment-activity",
943
945
  children: [
944
- ["delivering", "queued", "in_progress"].includes(run.status) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-agent-spinner", "aria-hidden": "true" }),
945
- run.label,
946
+ ["delivering", "queued", "in_progress"].includes(run2.status) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-agent-spinner", "aria-hidden": "true" }),
947
+ run2.label,
946
948
  ": ",
947
- labels[run.status]
949
+ labels[run2.status]
948
950
  ]
949
951
  },
950
952
  id
@@ -972,10 +974,10 @@ function DocxCommentActivity() {
972
974
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: entry.author || "Reviewer" }),
973
975
  /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "docx-full-comment-text", children: /* @__PURE__ */ jsxRuntime.jsx(ui.AiMarkdown, { allowHtml: false, children: commentText(entry) }) })
974
976
  ] }, entry.key)),
975
- statuses.map(([id, run]) => /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", className: "text-sm", children: [
976
- run.label,
977
+ statuses.map(([id, run2]) => /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", className: "text-sm", children: [
978
+ run2.label,
977
979
  ": ",
978
- labels[run.status]
980
+ labels[run2.status]
979
981
  ] }, id))
980
982
  ]
981
983
  }
@@ -991,10 +993,10 @@ function DocxMentions({
991
993
  notify
992
994
  }) {
993
995
  const review = useReview();
994
- const [activity, setActivity] = React3.useState({});
995
- const root = React3.useRef(null);
996
- const [composers, setComposers] = React3.useState([]);
997
- React3.useEffect(() => {
996
+ const [activity, setActivity] = React4.useState({});
997
+ const root = React4.useRef(null);
998
+ const [composers, setComposers] = React4.useState([]);
999
+ React4.useEffect(() => {
998
1000
  const element = root.current;
999
1001
  if (!element || !requestAgent) return;
1000
1002
  const discover = () => {
@@ -1020,15 +1022,15 @@ function DocxMentions({
1020
1022
  field.setSelectionRange(value.length, value.length);
1021
1023
  setSuggestions(null);
1022
1024
  };
1023
- const alive = React3.useRef(true);
1024
- React3.useEffect(() => {
1025
+ const alive = React4.useRef(true);
1026
+ React4.useEffect(() => {
1025
1027
  alive.current = true;
1026
1028
  return () => {
1027
1029
  alive.current = false;
1028
1030
  };
1029
1031
  }, []);
1030
- const activated = React3.useRef(void 0);
1031
- React3.useEffect(() => {
1032
+ const activated = React4.useRef(void 0);
1033
+ React4.useEffect(() => {
1032
1034
  if (!initialCommentId || activated.current === initialCommentId || !review.ready) return;
1033
1035
  const target = review.items.find(
1034
1036
  (item) => item.kind === "comment" && item.item.id === initialCommentId
@@ -1037,16 +1039,16 @@ function DocxMentions({
1037
1039
  review.setPaneOpen(true);
1038
1040
  if (review.setActive(target.key)) activated.current = initialCommentId;
1039
1041
  }, [initialCommentId, review]);
1040
- const input = React3.useRef(null);
1041
- const replyTarget = React3.useRef(null);
1042
- const pending = React3.useRef(null);
1043
- const [suggestions, setSuggestions] = React3.useState(null);
1044
- const [selected, setSelected] = React3.useState(0);
1042
+ const input = React4.useRef(null);
1043
+ const replyTarget = React4.useRef(null);
1044
+ const pending = React4.useRef(null);
1045
+ const [suggestions, setSuggestions] = React4.useState(null);
1046
+ const [selected, setSelected] = React4.useState(0);
1045
1047
  const candidates = chunk7UTB4PHM_cjs.filterMentionCandidates(
1046
1048
  mentionCandidates(mentions),
1047
1049
  suggestions?.query || ""
1048
1050
  ).slice(0, 8);
1049
- React3.useEffect(() => {
1051
+ React4.useEffect(() => {
1050
1052
  const submission = pending.current;
1051
1053
  if (!submission || !requestAgent) return;
1052
1054
  const created = review.items.find(
@@ -1287,26 +1289,36 @@ function DocxMentions({
1287
1289
  ) });
1288
1290
  }
1289
1291
  var DEFINED_TERM_STYLE = "DefinedTerm";
1290
- var FRAGMENT_STYLES = chunkAOFATOT3_cjs.stylesXml(
1292
+ var CROSS_REFERENCE_STYLE = "CrossReference";
1293
+ var BROKEN_CROSS_REFERENCE_STYLE = "CrossReferenceBroken";
1294
+ var CHARACTER_STYLES = {
1295
+ [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>`,
1296
+ [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>`,
1297
+ [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>`
1298
+ };
1299
+ function stylesUsed(body) {
1300
+ return [...new Set([...body.matchAll(/<w:rStyle w:val="([^"]+)"/g)].map((m) => m[1]))];
1301
+ }
1302
+ var fragmentStyles = (ids) => chunk2A4MDHJR_cjs.stylesXml(
1291
1303
  "",
1292
- `<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w: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>`
1304
+ `<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("")}`
1293
1305
  );
1294
- var textRun = (text, props = "") => `<w:r>${props ? `<w:rPr>${props}</w:rPr>` : ""}<w:t xml:space="preserve">${chunkAOFATOT3_cjs.esc(text)}</w:t></w:r>`;
1306
+ var textRun = (text, props = "") => `<w:r>${props ? `<w:rPr>${props}</w:rPr>` : ""}<w:t xml:space="preserve">${chunk2A4MDHJR_cjs.esc(text)}</w:t></w:r>`;
1295
1307
  function definitionTooltip(definition) {
1296
1308
  const line = `\u201C${definition.term}\u201D${definition.rest}`.replace(/\s+/g, " ").trim();
1297
1309
  return line.length > 255 ? `${line.slice(0, 254)}\u2026` : line;
1298
1310
  }
1299
1311
  function definitionParagraphXml(definition, bookmark, id = 0) {
1300
- return `<w:p><w:bookmarkStart w:id="${id}" w:name="${chunkAOFATOT3_cjs.esc(bookmark)}"/>${textRun("\u201C")}${textRun(
1312
+ return `<w:p><w:bookmarkStart w:id="${id}" w:name="${chunk2A4MDHJR_cjs.esc(bookmark)}"/>${textRun("\u201C")}${textRun(
1301
1313
  definition.term,
1302
1314
  "<w:b/>"
1303
1315
  )}${textRun("\u201D")}<w:bookmarkEnd w:id="${id}"/>${textRun(definition.rest)}</w:p>`;
1304
1316
  }
1305
1317
  function headingParagraphXml(text, styleId) {
1306
- return styleId ? `<w:p><w:pPr><w:pStyle w:val="${chunkAOFATOT3_cjs.esc(styleId)}"/></w:pPr>${textRun(text)}</w:p>` : `<w:p><w:pPr><w:keepNext/></w:pPr>${textRun(text, "<w:b/>")}</w:p>`;
1318
+ return styleId ? `<w:p><w:pPr><w:pStyle w:val="${chunk2A4MDHJR_cjs.esc(styleId)}"/></w:pPr>${textRun(text)}</w:p>` : `<w:p><w:pPr><w:keepNext/></w:pPr>${textRun(text, "<w:b/>")}</w:p>`;
1307
1319
  }
1308
1320
  function termLinkXml(term, bookmark, tooltip) {
1309
- return `<w:p><w:hyperlink w:anchor="${chunkAOFATOT3_cjs.esc(bookmark)}" w:tooltip="${chunkAOFATOT3_cjs.esc(tooltip)}" w:history="1">${textRun(
1321
+ return `<w:p><w:hyperlink w:anchor="${chunk2A4MDHJR_cjs.esc(bookmark)}" w:tooltip="${chunk2A4MDHJR_cjs.esc(tooltip)}" w:history="1">${textRun(
1310
1322
  term,
1311
1323
  `<w:rStyle w:val="${DEFINED_TERM_STYLE}"/>`
1312
1324
  )}</w:hyperlink></w:p>`;
@@ -1317,11 +1329,16 @@ function base64(bytes) {
1317
1329
  binary += String.fromCharCode(...bytes.subarray(i, i + 32768));
1318
1330
  return btoa(binary);
1319
1331
  }
1320
- function fragmentHtml(body, covered2, revision) {
1321
- const untracked = chunkAOFATOT3_cjs.docxPackage({
1322
- document: chunkAOFATOT3_cjs.documentXml(body),
1323
- styles: FRAGMENT_STYLES,
1324
- title: "Defined terms"
1332
+ function fragmentHtml(body, covered2, {
1333
+ revision,
1334
+ relationships,
1335
+ styles = stylesUsed(body)
1336
+ } = {}) {
1337
+ const untracked = chunk2A4MDHJR_cjs.docxPackage({
1338
+ document: chunk2A4MDHJR_cjs.documentXml(body),
1339
+ styles: fragmentStyles(styles),
1340
+ title: "Defined terms",
1341
+ relationships
1325
1342
  });
1326
1343
  const bytes = revision ? template.trackInsertion(untracked, revision, covered2) : untracked;
1327
1344
  return `<div data-docx-fragment="${base64(bytes)}" data-docx-fragment-end="${covered2 ? "covered" : "open"}"></div>`;
@@ -1343,14 +1360,14 @@ function findDefinitionsSection(paragraphs) {
1343
1360
  while (end < paragraphs.length && paragraphs[end].topLevel && !paragraphs[end].heading) end++;
1344
1361
  return { title, start: title + 1, end };
1345
1362
  }
1346
- var termOf = (paragraph) => chunkAOFATOT3_cjs.parseDefinition(paragraph.text)?.term ?? null;
1363
+ var termOf = (paragraph) => chunk2A4MDHJR_cjs.parseDefinition(paragraph.text)?.term ?? null;
1347
1364
  function insertionIndex(paragraphs, section, term, skip = /* @__PURE__ */ new Set()) {
1348
1365
  let afterLast = section.start;
1349
1366
  for (let i = section.start; i < section.end; i++) {
1350
1367
  if (skip.has(paragraphs[i].id)) continue;
1351
1368
  const other = termOf(paragraphs[i]);
1352
1369
  if (other === null) continue;
1353
- if (chunkAOFATOT3_cjs.compareTerms(other, term) > 0) return i;
1370
+ if (chunk2A4MDHJR_cjs.compareTerms(other, term) > 0) return i;
1354
1371
  afterLast = i + 1;
1355
1372
  }
1356
1373
  return afterLast;
@@ -1377,7 +1394,7 @@ function insertParagraphs(port, index, body, count, keep) {
1377
1394
  function addDefinition(port, definition, keep) {
1378
1395
  const paragraphs = port.paragraphs();
1379
1396
  const section = findDefinitionsSection(paragraphs);
1380
- const paragraph = definitionParagraphXml(definition, chunkAOFATOT3_cjs.definitionBookmark(definition.id));
1397
+ const paragraph = definitionParagraphXml(definition, chunk2A4MDHJR_cjs.definitionBookmark(definition.id));
1381
1398
  if (section)
1382
1399
  return insertParagraphs(
1383
1400
  port,
@@ -1403,7 +1420,7 @@ function insertDefinedTerm(port, definition, options = {}) {
1403
1420
  caret = { paragraphId: start.paragraphId, offset: Math.max(0, start.offset - options.replace) };
1404
1421
  port.deleteRange(caret, start);
1405
1422
  }
1406
- const bookmark = chunkAOFATOT3_cjs.definitionBookmark(definition.id);
1423
+ const bookmark = chunk2A4MDHJR_cjs.definitionBookmark(definition.id);
1407
1424
  const addedDefinition = !hasBookmark(port.paragraphs(), bookmark);
1408
1425
  if (addedDefinition) caret = addDefinition(port, definition, caret) ?? caret;
1409
1426
  port.setCaret(caret);
@@ -1417,12 +1434,96 @@ function insertDefinedTerm(port, definition, options = {}) {
1417
1434
  return { addedDefinition };
1418
1435
  }
1419
1436
  function definitionOfAnchor(anchor, definitions) {
1420
- const id = chunkAOFATOT3_cjs.definitionIdOfBookmark(anchor.replace(/^#/, ""));
1437
+ const id = chunk2A4MDHJR_cjs.definitionIdOfBookmark(anchor.replace(/^#/, ""));
1421
1438
  return id ? definitions.get(id) : void 0;
1422
1439
  }
1440
+ function LinkHoverCard({
1441
+ root,
1442
+ matches,
1443
+ resolve,
1444
+ onFirstHover,
1445
+ testId
1446
+ }) {
1447
+ const [card, setCard] = React4.useState(null);
1448
+ const hovered = React4.useRef(false);
1449
+ const latest = React4.useRef({ matches, onFirstHover });
1450
+ latest.current = { matches, onFirstHover };
1451
+ React4.useEffect(() => {
1452
+ if (!root) return;
1453
+ const over = (event) => {
1454
+ const link = event.target?.closest?.(
1455
+ "a.docx-hyperlink"
1456
+ );
1457
+ const href = link?.getAttribute("href") ?? "";
1458
+ if (!link || !href || !latest.current.matches(href, link)) return;
1459
+ if (!hovered.current) {
1460
+ hovered.current = true;
1461
+ latest.current.onFirstHover?.();
1462
+ }
1463
+ const title = link.getAttribute("title");
1464
+ if (title) {
1465
+ link.dataset.hoverTitle = title;
1466
+ link.removeAttribute("title");
1467
+ }
1468
+ const rect = link.getBoundingClientRect();
1469
+ setCard({
1470
+ left: rect.left,
1471
+ top: rect.bottom + 6,
1472
+ href,
1473
+ fallback: link.dataset.hoverTitle ?? ""
1474
+ });
1475
+ };
1476
+ const out = (event) => {
1477
+ const link = event.target?.closest?.("a.docx-hyperlink");
1478
+ if (link && !link.contains(event.relatedTarget)) setCard(null);
1479
+ };
1480
+ const hide = () => setCard(null);
1481
+ root.addEventListener("mouseover", over);
1482
+ root.addEventListener("mouseout", out);
1483
+ window.addEventListener("keydown", hide, true);
1484
+ window.addEventListener("pointerdown", hide, true);
1485
+ window.addEventListener("scroll", hide, true);
1486
+ return () => {
1487
+ root.removeEventListener("mouseover", over);
1488
+ root.removeEventListener("mouseout", out);
1489
+ window.removeEventListener("keydown", hide, true);
1490
+ window.removeEventListener("pointerdown", hide, true);
1491
+ window.removeEventListener("scroll", hide, true);
1492
+ };
1493
+ }, [root]);
1494
+ if (!card) return null;
1495
+ const content = resolve(card.href);
1496
+ if (!content && !card.fallback) return null;
1497
+ return reactDom.createPortal(
1498
+ /* @__PURE__ */ jsxRuntime.jsx(
1499
+ "div",
1500
+ {
1501
+ role: "tooltip",
1502
+ className: "native-docx-link-card rounded-md border border-border bg-popover p-3 text-sm text-popover-foreground shadow-lg",
1503
+ style: {
1504
+ position: "fixed",
1505
+ left: Math.max(8, Math.min(card.left, window.innerWidth - 348)),
1506
+ top: card.top,
1507
+ width: 340,
1508
+ zIndex: 1e3,
1509
+ pointerEvents: "none"
1510
+ },
1511
+ "data-testid": testId,
1512
+ children: content ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1513
+ content.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: content.title }),
1514
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: content.title ? "mt-1 text-muted-foreground" : void 0, children: content.body }),
1515
+ content.footer && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: content.footer })
1516
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: card.fallback })
1517
+ }
1518
+ ),
1519
+ document.body
1520
+ );
1521
+ }
1423
1522
 
1424
1523
  // src/docx/definitions/port.ts
1524
+ var WATCHED_STYLES = /* @__PURE__ */ new Set([BROKEN_CROSS_REFERENCE_STYLE]);
1425
1525
  var attr = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
1526
+ var FIELD_ATOM = "\uFFFC";
1426
1527
  var HEADING_STYLE = /^(heading|berschrift|titre|t[ií]tulo|titolo|kop)\s*\d/i;
1427
1528
  function readParagraphs(root) {
1428
1529
  const out = [];
@@ -1449,8 +1550,44 @@ function readParagraph(node, topLevel, bookmarks) {
1449
1550
  const links = [];
1450
1551
  let styleId;
1451
1552
  let outline = false;
1553
+ let fieldDepth = 0;
1554
+ const marks = [];
1555
+ let runStyle;
1556
+ const fields = [];
1557
+ let current = null;
1558
+ const field = (c) => {
1559
+ const type = attr(c, "fldCharType");
1560
+ if (type === "begin") {
1561
+ if (fieldDepth === 0) {
1562
+ current = { offset: text.length, instruction: "", result: "", inResult: false };
1563
+ text += FIELD_ATOM;
1564
+ }
1565
+ fieldDepth++;
1566
+ } else if (type === "separate" && fieldDepth === 1 && current) current.inResult = true;
1567
+ else if (type === "end") {
1568
+ fieldDepth = Math.max(0, fieldDepth - 1);
1569
+ if (fieldDepth === 0 && current) {
1570
+ const { offset, instruction, result } = current;
1571
+ fields.push({ offset, instruction: instruction.trim(), result });
1572
+ current = null;
1573
+ }
1574
+ }
1575
+ };
1452
1576
  const walk = (n, link) => {
1453
1577
  for (const c of n.children ?? []) {
1578
+ if (c.localName === "fldChar") {
1579
+ field(c);
1580
+ continue;
1581
+ }
1582
+ if (c.localName === "fldSimple") {
1583
+ if (fieldDepth === 0) text += FIELD_ATOM;
1584
+ continue;
1585
+ }
1586
+ if (c.localName === "instrText") {
1587
+ if (fieldDepth === 1 && current)
1588
+ current.instruction += (c.children ?? []).map((t) => t.value ?? "").join("");
1589
+ continue;
1590
+ }
1454
1591
  if (c.kind === "paragraphProperties" || c.localName === "pPr") {
1455
1592
  for (const p of c.children ?? []) {
1456
1593
  if (p.localName === "pStyle") styleId = attr(p, "val");
@@ -1459,6 +1596,14 @@ function readParagraph(node, topLevel, bookmarks) {
1459
1596
  continue;
1460
1597
  }
1461
1598
  if (c.localName === "delText" || c.localName === "del" || c.localName === "rPr") continue;
1599
+ if (c.localName === "r") {
1600
+ const rStyle = c.children?.find((x) => x.localName === "rPr")?.children?.find((x) => x.localName === "rStyle");
1601
+ const watched = rStyle && attr(rStyle, "val");
1602
+ runStyle = watched && WATCHED_STYLES.has(watched) ? watched : void 0;
1603
+ walk(c, link);
1604
+ runStyle = void 0;
1605
+ continue;
1606
+ }
1462
1607
  if (c.localName === "bookmarkStart") {
1463
1608
  const name = attr(c, "name");
1464
1609
  if (name) bookmarks.push(name);
@@ -1472,11 +1617,22 @@ function readParagraph(node, topLevel, bookmarks) {
1472
1617
  continue;
1473
1618
  }
1474
1619
  if (c.kind === "textValue") {
1620
+ if (fieldDepth > 0) {
1621
+ const open = current;
1622
+ if (fieldDepth === 1 && open?.inResult) open.result += c.value ?? "";
1623
+ continue;
1624
+ }
1625
+ if (runStyle && c.value) {
1626
+ const last = marks[marks.length - 1];
1627
+ if (last && last.styleId === runStyle && last.offset + last.text.length === text.length)
1628
+ last.text += c.value;
1629
+ else marks.push({ styleId: runStyle, offset: text.length, text: c.value });
1630
+ }
1475
1631
  text += c.value ?? "";
1476
1632
  if (link) link.text += c.value ?? "";
1477
1633
  continue;
1478
1634
  }
1479
- if (c.localName === "tab") text += " ";
1635
+ if (c.localName === "tab" && fieldDepth === 0) text += " ";
1480
1636
  walk(c, link);
1481
1637
  }
1482
1638
  };
@@ -1488,9 +1644,20 @@ function readParagraph(node, topLevel, bookmarks) {
1488
1644
  styleId,
1489
1645
  topLevel,
1490
1646
  bookmarks,
1491
- links
1647
+ links,
1648
+ ...fields.length ? { fields } : {},
1649
+ ...marks.length ? { marks } : {}
1492
1650
  };
1493
1651
  }
1652
+ function documentStyleIds(root) {
1653
+ const ids = /* @__PURE__ */ new Set();
1654
+ for (const style of root?.children ?? [])
1655
+ if (style.localName === "style") {
1656
+ const id = attr(style, "styleId");
1657
+ if (id) ids.add(id);
1658
+ }
1659
+ return ids;
1660
+ }
1494
1661
  function editorPort(editor, revision) {
1495
1662
  const surface = () => {
1496
1663
  const s = editor.surface;
@@ -1510,8 +1677,17 @@ function editorPort(editor, revision) {
1510
1677
  surface().setSelection({ anchor: from, head: to });
1511
1678
  surface().deleteSelection();
1512
1679
  },
1513
- paste: (body, text, covered2) => editor.exec({ type: "paste", text, html: fragmentHtml(body, covered2, revision) }).ok,
1514
- splitParagraph: () => surface().splitParagraph()
1680
+ paste: (body, text, covered2, relationships) => {
1681
+ const defined = documentStyleIds(surface().session.stylesRoot());
1682
+ const styles = stylesUsed(body).filter((id) => !defined.has(id));
1683
+ return editor.exec({
1684
+ type: "paste",
1685
+ text,
1686
+ html: fragmentHtml(body, covered2, { revision, relationships, styles })
1687
+ }).ok;
1688
+ },
1689
+ splitParagraph: () => surface().splitParagraph(),
1690
+ typeText: (text) => surface().insertPlainText(text)
1515
1691
  };
1516
1692
  }
1517
1693
  function withDirectEditing(editor, fn) {
@@ -1524,34 +1700,68 @@ function withDirectEditing(editor, fn) {
1524
1700
  if (mode === "suggesting") editor.setEditingMode("suggesting");
1525
1701
  }
1526
1702
  }
1527
- function holdCaret(editor, timeoutMs = 5e3) {
1703
+ function holdCaret(editor, { settleMs = 600, maxMs = 2e3 } = {}) {
1528
1704
  const surface = editor.surface;
1529
1705
  const selection = surface?.state().selection;
1530
1706
  if (!surface || !selection) return;
1531
- const { paragraphId, offset } = selection.head;
1532
- const paraId = surface.session.paraIdOf(paragraphId);
1707
+ const { offset } = selection.head;
1708
+ const paraId = surface.session.paraIdOf(selection.head.paragraphId);
1533
1709
  if (!paraId) return;
1710
+ let typed = "";
1534
1711
  let done = false;
1712
+ let settle;
1535
1713
  const stop = () => {
1536
1714
  done = true;
1537
1715
  offChange();
1538
- offSelection();
1539
- clearTimeout(timer);
1716
+ clearTimeout(settle);
1717
+ clearTimeout(limit);
1718
+ window.removeEventListener("keydown", key, true);
1719
+ window.removeEventListener("pointerdown", click, true);
1540
1720
  };
1541
- const restore = () => {
1721
+ const finish = () => {
1542
1722
  if (done) return;
1543
- const now = surface.state().selection;
1544
- const node = surface.session.nodeIdOf(paraId);
1545
- if (!now || !node) return;
1546
- if (now.head.offset !== offset || now.head.paragraphId !== paragraphId) return stop();
1547
- if (node === paragraphId) return;
1548
1723
  stop();
1724
+ const node = surface.session.nodeIdOf(paraId);
1725
+ if (!node) return;
1549
1726
  const point = { paragraphId: node, offset };
1550
1727
  surface.setSelection({ anchor: point, head: point });
1728
+ if (typed) surface.insertPlainText(typed);
1551
1729
  };
1552
- const offChange = editor.on("change", restore);
1553
- const offSelection = editor.on("selectionChange", restore);
1554
- const timer = setTimeout(stop, timeoutMs);
1730
+ const key = (event) => {
1731
+ if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
1732
+ event.preventDefault();
1733
+ event.stopPropagation();
1734
+ typed += event.key;
1735
+ return;
1736
+ }
1737
+ finish();
1738
+ };
1739
+ const click = () => {
1740
+ if (typed) finish();
1741
+ else stop();
1742
+ };
1743
+ const quiet = () => {
1744
+ clearTimeout(settle);
1745
+ settle = setTimeout(finish, settleMs);
1746
+ };
1747
+ const offChange = editor.on("change", quiet);
1748
+ window.addEventListener("keydown", key, true);
1749
+ window.addEventListener("pointerdown", click, true);
1750
+ settle = setTimeout(finish, settleMs);
1751
+ const limit = setTimeout(finish, maxMs);
1752
+ }
1753
+ function preservingCaret(editor, fn) {
1754
+ const surface = editor.surface;
1755
+ const before = surface?.state().selection?.head;
1756
+ const paraId = before && surface?.session.paraIdOf(before.paragraphId);
1757
+ const result = fn();
1758
+ const node = paraId && surface?.session.nodeIdOf(paraId);
1759
+ if (before && node) {
1760
+ const point = { paragraphId: node, offset: before.offset };
1761
+ surface.setSelection({ anchor: point, head: point });
1762
+ holdCaret(editor);
1763
+ }
1764
+ return result;
1555
1765
  }
1556
1766
 
1557
1767
  // src/docx/structural/trackedOrNoted.ts
@@ -1608,11 +1818,11 @@ function structuralPort(editor) {
1608
1818
  }
1609
1819
  };
1610
1820
  }
1611
- var DocxAuthorContext = React3.createContext("You");
1821
+ var DocxAuthorContext = React4.createContext("You");
1612
1822
  function useTrackedOrNoted() {
1613
1823
  const editor = react.useDocxEditor();
1614
- const author = React3.useContext(DocxAuthorContext);
1615
- return React3.useCallback(
1824
+ const author = React4.useContext(DocxAuthorContext);
1825
+ return React4.useCallback(
1616
1826
  (spec) => editor ? trackedOrNoted(structuralPort(editor), { ...spec, author }) : void 0,
1617
1827
  [editor, author]
1618
1828
  );
@@ -1632,8 +1842,8 @@ var DEFAULT_DEFINED_TERMS_LABELS = {
1632
1842
  preferred: "Preferred",
1633
1843
  alsoIn: (source) => `Also defined${source ? ` in ${source}` : ""}`
1634
1844
  };
1635
- var DefinedTermsContext = React3.createContext(null);
1636
- var useDefinedTerms = () => React3.useContext(DefinedTermsContext);
1845
+ var DefinedTermsContext = React4.createContext(null);
1846
+ var useDefinedTerms = () => React4.useContext(DefinedTermsContext);
1637
1847
  function rowsOf(groups) {
1638
1848
  return groups.flatMap(
1639
1849
  (group) => group.definitions.map((definition, i) => ({ group, definition, variant: i > 0 }))
@@ -1649,16 +1859,16 @@ function DefinedTermsProvider({
1649
1859
  }) {
1650
1860
  const editor = react.useDocxEditor();
1651
1861
  const track = useTrackedOrNoted();
1652
- const l = React3.useMemo(() => ({ ...DEFAULT_DEFINED_TERMS_LABELS, ...labels }), [labels]);
1653
- const [sources, setSources] = React3.useState(null);
1654
- const loadedAt = React3.useRef(0);
1655
- const loading = React3.useRef(null);
1656
- const [labelId, setLabelId] = React3.useState(null);
1657
- const [picker, setPicker] = React3.useState(null);
1658
- const [selected, setSelected] = React3.useState(0);
1659
- const marker = React3.useRef(null);
1660
- const dismissedAt = React3.useRef(null);
1661
- const refresh = React3.useCallback(
1862
+ const l = React4.useMemo(() => ({ ...DEFAULT_DEFINED_TERMS_LABELS, ...labels }), [labels]);
1863
+ const [sources, setSources] = React4.useState(null);
1864
+ const loadedAt = React4.useRef(0);
1865
+ const loading = React4.useRef(null);
1866
+ const [labelId, setLabelId] = React4.useState(null);
1867
+ const [picker, setPicker] = React4.useState(null);
1868
+ const [selected, setSelected] = React4.useState(0);
1869
+ const marker = React4.useRef(null);
1870
+ const dismissedAt = React4.useRef(null);
1871
+ const refresh = React4.useCallback(
1662
1872
  (force = false) => {
1663
1873
  if (!load) return Promise.resolve([]);
1664
1874
  if (!force && sources && Date.now() - loadedAt.current < STALE_AFTER_MS)
@@ -1682,29 +1892,29 @@ function DefinedTermsProvider({
1682
1892
  },
1683
1893
  [load, sources, notify]
1684
1894
  );
1685
- const all = React3.useMemo(() => chunkAOFATOT3_cjs.groupDefinitions(sources ?? []).groups, [sources]);
1686
- const byId = React3.useMemo(
1895
+ const all = React4.useMemo(() => chunk2A4MDHJR_cjs.groupDefinitions(sources ?? []).groups, [sources]);
1896
+ const byId = React4.useMemo(
1687
1897
  () => new Map(all.flatMap((g) => g.definitions).map((d) => [d.id, d])),
1688
1898
  [all]
1689
1899
  );
1690
- const agreements = React3.useMemo(() => chunkAOFATOT3_cjs.definitionLabels(sources ?? []), [sources]);
1691
- const groups = React3.useMemo(
1692
- () => picker ? chunkAOFATOT3_cjs.filterTermGroups(chunkAOFATOT3_cjs.groupDefinitions(sources ?? [], { labelId }).groups, picker.query).slice(
1900
+ const agreements = React4.useMemo(() => chunk2A4MDHJR_cjs.definitionLabels(sources ?? []), [sources]);
1901
+ const groups = React4.useMemo(
1902
+ () => picker ? chunk2A4MDHJR_cjs.filterTermGroups(chunk2A4MDHJR_cjs.groupDefinitions(sources ?? [], { labelId }).groups, picker.query).slice(
1693
1903
  0,
1694
1904
  MAX_GROUPS
1695
1905
  ) : [],
1696
1906
  [sources, labelId, picker]
1697
1907
  );
1698
- const rows = React3.useMemo(() => rowsOf(groups), [groups]);
1699
- React3.useEffect(() => setSelected(0), [picker?.query, labelId]);
1908
+ const rows = React4.useMemo(() => rowsOf(groups), [groups]);
1909
+ React4.useEffect(() => setSelected(0), [picker?.query, labelId]);
1700
1910
  const container = () => marker.current?.closest(".native-docx-viewer") ?? document.body;
1701
- const [viewer, setViewer] = React3.useState(null);
1702
- React3.useEffect(() => setViewer(container()), []);
1703
- const refreshRef = React3.useRef(refresh);
1911
+ const [viewer, setViewer] = React4.useState(null);
1912
+ React4.useEffect(() => setViewer(container()), []);
1913
+ const refreshRef = React4.useRef(refresh);
1704
1914
  refreshRef.current = refresh;
1705
- const firstHover = React3.useCallback(() => void refreshRef.current(), []);
1915
+ const firstHover = React4.useCallback(() => void refreshRef.current(), []);
1706
1916
  const caretRect = () => container().querySelector(".docx-editor-one-surface__caret")?.getBoundingClientRect();
1707
- const attempt = React3.useCallback(
1917
+ const attempt = React4.useCallback(
1708
1918
  (fn) => {
1709
1919
  try {
1710
1920
  return fn();
@@ -1715,19 +1925,26 @@ function DefinedTermsProvider({
1715
1925
  },
1716
1926
  [notify]
1717
1927
  );
1718
- const run = React3.useCallback(
1928
+ const run2 = React4.useCallback(
1719
1929
  (fn) => editor ? attempt(() => withDirectEditing(editor, fn)) : void 0,
1720
1930
  [editor, attempt]
1721
1931
  );
1722
- const pick = React3.useCallback(
1932
+ const typedTrigger = (port) => {
1933
+ if (picker?.mode !== "typing") return 0;
1934
+ const caret = port.caret();
1935
+ const paragraph = caret && port.paragraphs().find((p) => p.id === caret.paragraphId);
1936
+ const match = paragraph && TRIGGER_QUERY.exec(paragraph.text.slice(0, caret.offset));
1937
+ return match ? DEFINED_TERM_TRIGGER.length + match[1].length : 0;
1938
+ };
1939
+ const pick = React4.useCallback(
1723
1940
  (row) => {
1724
1941
  if (!editor || !picker || !row) return;
1725
1942
  const port = editorPort(editor);
1726
- const placed = run(() => {
1943
+ const placed = run2(() => {
1727
1944
  if (picker.mode === "search" && picker.caret) port.setCaret(picker.caret);
1728
1945
  const caret = port.caret();
1729
1946
  if (!caret) throw new Error("Place the cursor where the term should go.");
1730
- const typed = picker.mode === "typing" ? DEFINED_TERM_TRIGGER.length + picker.query.length : 0;
1947
+ const typed = typedTrigger(port);
1731
1948
  if (typed) port.deleteRange({ ...caret, offset: Math.max(0, caret.offset - typed) }, caret);
1732
1949
  return true;
1733
1950
  });
@@ -1743,9 +1960,9 @@ function DefinedTermsProvider({
1743
1960
  if (result?.addedDefinition)
1744
1961
  notify?.(`\u201C${row.definition.term}\u201D added to the Definitions section.`, "success");
1745
1962
  },
1746
- [editor, picker, run, attempt, track, notify]
1963
+ [editor, picker, run2, attempt, track, notify]
1747
1964
  );
1748
- const openPicker = React3.useCallback(
1965
+ const openPicker = React4.useCallback(
1749
1966
  (anchor) => {
1750
1967
  if (!editor || !editable) return;
1751
1968
  const caret = editorPort(editor).caret();
@@ -1762,7 +1979,7 @@ function DefinedTermsProvider({
1762
1979
  // eslint-disable-next-line react-hooks/exhaustive-deps
1763
1980
  [editor, editable, refresh]
1764
1981
  );
1765
- React3.useEffect(() => {
1982
+ React4.useEffect(() => {
1766
1983
  if (!editor || !editable || !load) return;
1767
1984
  let frame = 0;
1768
1985
  const check = () => {
@@ -1797,7 +2014,7 @@ function DefinedTermsProvider({
1797
2014
  offSelection();
1798
2015
  };
1799
2016
  }, [editor, editable, load, refresh]);
1800
- React3.useEffect(() => {
2017
+ React4.useEffect(() => {
1801
2018
  if (picker?.mode !== "typing") return;
1802
2019
  const keys = (event) => {
1803
2020
  if (event.key === "Escape") {
@@ -1814,7 +2031,7 @@ function DefinedTermsProvider({
1814
2031
  window.addEventListener("keydown", keys, true);
1815
2032
  return () => window.removeEventListener("keydown", keys, true);
1816
2033
  }, [picker, rows, selected, pick]);
1817
- const value = React3.useMemo(
2034
+ const value = React4.useMemo(
1818
2035
  () => load && editable ? { openPicker, labels: l } : null,
1819
2036
  [load, editable, openPicker, l]
1820
2037
  );
@@ -1822,11 +2039,16 @@ function DefinedTermsProvider({
1822
2039
  /* @__PURE__ */ jsxRuntime.jsx("span", { ref: marker, hidden: true }),
1823
2040
  children,
1824
2041
  load && /* @__PURE__ */ jsxRuntime.jsx(
1825
- DefinedTermHover,
2042
+ LinkHoverCard,
1826
2043
  {
1827
2044
  root: viewer,
1828
- resolve: (anchor) => definitionOfAnchor(anchor, byId),
1829
- onFirstHover: firstHover
2045
+ matches: (href) => href.startsWith("#_dt_"),
2046
+ resolve: (href) => {
2047
+ const definition = definitionOfAnchor(href, byId);
2048
+ return definition ? { title: definition.term, body: definition.meaning, footer: sourceOf(definition) } : null;
2049
+ },
2050
+ onFirstHover: firstHover,
2051
+ testId: "docx-defined-term-card"
1830
2052
  }
1831
2053
  ),
1832
2054
  picker && reactDom.createPortal(
@@ -1868,17 +2090,17 @@ function DefinedTermMenu({
1868
2090
  onClose,
1869
2091
  labels: l
1870
2092
  }) {
1871
- const listboxId = React3__default.default.useId();
1872
- const element = React3.useRef(null);
2093
+ const listboxId = React4__default.default.useId();
2094
+ const element = React4.useRef(null);
1873
2095
  const search = picker.mode === "search";
1874
- React3.useEffect(() => {
2096
+ React4.useEffect(() => {
1875
2097
  const dismiss = (event) => {
1876
2098
  if (!element.current?.contains(event.target)) onClose();
1877
2099
  };
1878
2100
  document.addEventListener("pointerdown", dismiss);
1879
2101
  return () => document.removeEventListener("pointerdown", dismiss);
1880
2102
  }, [onClose]);
1881
- React3.useEffect(() => {
2103
+ React4.useEffect(() => {
1882
2104
  element.current?.querySelector(`[data-index="${selected}"]`)?.scrollIntoView?.({ block: "nearest" });
1883
2105
  }, [selected]);
1884
2106
  const left = Math.max(8, Math.min(picker.left, window.innerWidth - 368));
@@ -1979,83 +2201,6 @@ function DefinedTermMenu({
1979
2201
  }
1980
2202
  );
1981
2203
  }
1982
- function DefinedTermHover({
1983
- root,
1984
- resolve,
1985
- onFirstHover
1986
- }) {
1987
- const [card, setCard] = React3.useState(null);
1988
- const hovered = React3.useRef(false);
1989
- React3.useEffect(() => {
1990
- if (!root) return;
1991
- const over = (event) => {
1992
- const link = event.target?.closest?.(
1993
- 'a.docx-hyperlink[data-docx-link-kind="internal"]'
1994
- );
1995
- const href = link?.getAttribute("href") ?? "";
1996
- if (!link || !href.startsWith("#_dt_")) return;
1997
- if (!hovered.current) {
1998
- hovered.current = true;
1999
- onFirstHover();
2000
- }
2001
- const title = link.getAttribute("title");
2002
- if (title) {
2003
- link.dataset.definition = title;
2004
- link.removeAttribute("title");
2005
- }
2006
- const rect = link.getBoundingClientRect();
2007
- setCard({
2008
- left: rect.left,
2009
- top: rect.bottom + 6,
2010
- anchor: href.slice(1),
2011
- fallback: link.dataset.definition ?? ""
2012
- });
2013
- };
2014
- const out = (event) => {
2015
- const link = event.target?.closest?.("a.docx-hyperlink");
2016
- if (link && !link.contains(event.relatedTarget)) setCard(null);
2017
- };
2018
- root.addEventListener("mouseover", over);
2019
- root.addEventListener("mouseout", out);
2020
- const hide = () => setCard(null);
2021
- window.addEventListener("keydown", hide, true);
2022
- window.addEventListener("pointerdown", hide, true);
2023
- window.addEventListener("scroll", hide, true);
2024
- return () => {
2025
- root.removeEventListener("mouseover", over);
2026
- root.removeEventListener("mouseout", out);
2027
- window.removeEventListener("keydown", hide, true);
2028
- window.removeEventListener("pointerdown", hide, true);
2029
- window.removeEventListener("scroll", hide, true);
2030
- };
2031
- }, [root, onFirstHover]);
2032
- if (!card) return null;
2033
- const definition = resolve(card.anchor);
2034
- return reactDom.createPortal(
2035
- /* @__PURE__ */ jsxRuntime.jsx(
2036
- "div",
2037
- {
2038
- role: "tooltip",
2039
- className: "native-docx-term-card rounded-md border border-border bg-popover p-3 text-sm text-popover-foreground shadow-lg",
2040
- style: {
2041
- position: "fixed",
2042
- left: Math.max(8, Math.min(card.left, window.innerWidth - 348)),
2043
- top: card.top,
2044
- width: 340,
2045
- zIndex: 1e3,
2046
- pointerEvents: "none"
2047
- },
2048
- "data-testid": "docx-defined-term-card",
2049
- children: definition ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2050
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: definition.term }),
2051
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-muted-foreground", children: definition.meaning }),
2052
- sourceOf(definition) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: sourceOf(definition) })
2053
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: card.fallback })
2054
- }
2055
- ),
2056
- document.body
2057
- );
2058
- }
2059
2204
  var BUILTIN_TEMPLATE_NAME = "ARBI legal template";
2060
2205
  var templateFileName = (t) => /\.(dotx|dotm|docx|docm)$/i.test(t.name) ? t.name : `${t.name}.dotx`;
2061
2206
  var builtin;
@@ -2071,8 +2216,8 @@ async function resolveHouseTemplate(host) {
2071
2216
  return builtinHouseTemplate();
2072
2217
  }
2073
2218
  }
2074
- var HouseTemplateContext = React3.createContext(null);
2075
- var useHouseTemplate = () => React3.useContext(HouseTemplateContext);
2219
+ var HouseTemplateContext = React4.createContext(null);
2220
+ var useHouseTemplate = () => React4.useContext(HouseTemplateContext);
2076
2221
  function HouseTemplateProvider({
2077
2222
  host,
2078
2223
  documentId,
@@ -2083,26 +2228,26 @@ function HouseTemplateProvider({
2083
2228
  }) {
2084
2229
  const editor = react.useDocxEditor();
2085
2230
  const track = useTrackedOrNoted();
2086
- const [template$1, setTemplate] = React3.useState(builtinHouseTemplate);
2087
- const [divergence, setDivergence] = React3.useState(null);
2088
- const [basedOnTemplate, setBasedOnTemplate] = React3.useState(false);
2089
- const [levels, setLevels] = React3.useState({});
2090
- const [generation, setGeneration] = React3.useState(0);
2091
- React3.useEffect(() => {
2231
+ const [template$1, setTemplate] = React4.useState(builtinHouseTemplate);
2232
+ const [divergence, setDivergence] = React4.useState(null);
2233
+ const [basedOnTemplate, setBasedOnTemplate] = React4.useState(false);
2234
+ const [levels, setLevels] = React4.useState({});
2235
+ const [generation, setGeneration] = React4.useState(0);
2236
+ React4.useEffect(() => {
2092
2237
  let live = true;
2093
2238
  void resolveHouseTemplate(host).then((t) => live && setTemplate(t));
2094
2239
  return () => {
2095
2240
  live = false;
2096
2241
  };
2097
2242
  }, [host]);
2098
- const blocks = React3.useMemo(() => {
2243
+ const blocks = React4.useMemo(() => {
2099
2244
  try {
2100
2245
  return template.listBuildingBlocks(template$1.bytes);
2101
2246
  } catch {
2102
2247
  return [];
2103
2248
  }
2104
2249
  }, [template$1]);
2105
- React3.useEffect(() => {
2250
+ React4.useEffect(() => {
2106
2251
  if (!editor || !enabled) return;
2107
2252
  let live = true;
2108
2253
  void editor.save().then((saved) => {
@@ -2116,8 +2261,8 @@ function HouseTemplateProvider({
2116
2261
  live = false;
2117
2262
  };
2118
2263
  }, [editor, template$1, generation, enabled]);
2119
- const refresh = React3.useCallback(() => setGeneration((g) => g + 1), []);
2120
- const insertBlock = React3.useCallback(
2264
+ const refresh = React4.useCallback(() => setGeneration((g) => g + 1), []);
2265
+ const insertBlock = React4.useCallback(
2121
2266
  (name) => {
2122
2267
  if (!editor || !editable) return false;
2123
2268
  const fragment = template.buildingBlockFragment(template$1.bytes, name);
@@ -2147,7 +2292,7 @@ function HouseTemplateProvider({
2147
2292
  },
2148
2293
  [editor, editable, template$1, notify, refresh, track]
2149
2294
  );
2150
- const setAsHouseTemplate = React3.useMemo(
2295
+ const setAsHouseTemplate = React4.useMemo(
2151
2296
  () => host?.setFromDocument && documentId ? async () => {
2152
2297
  try {
2153
2298
  await host.setFromDocument(documentId);
@@ -2162,7 +2307,7 @@ function HouseTemplateProvider({
2162
2307
  } : void 0,
2163
2308
  [host, documentId, notify]
2164
2309
  );
2165
- const value = React3.useMemo(
2310
+ const value = React4.useMemo(
2166
2311
  () => ({
2167
2312
  template: template$1,
2168
2313
  blocks,
@@ -2188,17 +2333,838 @@ function HouseTemplateProvider({
2188
2333
  );
2189
2334
  return /* @__PURE__ */ jsxRuntime.jsx(HouseTemplateContext.Provider, { value: enabled ? value : null, children });
2190
2335
  }
2336
+
2337
+ // src/docx/references/numbering.ts
2338
+ var numbers = (level) => !!level && level.numFmt !== "bullet" && level.numFmt !== "none" && (level.lvlText ?? level.markerText ?? "").length > 0;
2339
+ function paragraphNumber(order, items, levelOf, paragraphId) {
2340
+ const item = items.get(paragraphId);
2341
+ if (!item || !numbers(item)) return null;
2342
+ const at = order.indexOf(paragraphId);
2343
+ const markerAt = (ilvl) => {
2344
+ if (ilvl === item.ilvl) return item.markerText;
2345
+ for (let i = at - 1; i >= 0; i--) {
2346
+ const other = items.get(order[i]);
2347
+ if (other && other.numId === item.numId && other.ilvl === ilvl) return other.markerText;
2348
+ }
2349
+ return null;
2350
+ };
2351
+ const chain = [];
2352
+ const texts = [];
2353
+ for (let u = item.ilvl; u >= 0; u--) {
2354
+ const level = levelOf(item.numId, u);
2355
+ if (!level || !numbers(level)) continue;
2356
+ if (u !== item.ilvl && texts.some((t) => t.includes(`%${u + 1}`))) continue;
2357
+ chain.push(u);
2358
+ texts.push(level.lvlText);
2359
+ }
2360
+ const value = chain.reverse().map((u) => markerAt(u) ?? "").join("");
2361
+ if (!value) return null;
2362
+ return value.length > 1 && value.endsWith(".") ? value.slice(0, -1) : value;
2363
+ }
2364
+ function listTargets(paragraphs, items, levelOf) {
2365
+ const order = paragraphs.map((p) => p.id);
2366
+ const out = [];
2367
+ for (const p of paragraphs) {
2368
+ const text = p.text.replace(//g, "").trim();
2369
+ if (!text) continue;
2370
+ const number = paragraphNumber(order, items, levelOf, p.id);
2371
+ const item = items.get(p.id);
2372
+ if (number !== null)
2373
+ out.push({
2374
+ paragraphId: p.id,
2375
+ kind: "numbered",
2376
+ number,
2377
+ marker: item?.markerText ?? "",
2378
+ text,
2379
+ heading: p.heading,
2380
+ level: item?.ilvl ?? 0
2381
+ });
2382
+ else if (p.heading)
2383
+ out.push({
2384
+ paragraphId: p.id,
2385
+ kind: "heading",
2386
+ number: null,
2387
+ marker: "",
2388
+ text,
2389
+ heading: true,
2390
+ level: 0
2391
+ });
2392
+ }
2393
+ return out;
2394
+ }
2395
+ function filterTargets(targets, query) {
2396
+ const q = query.trim().toLowerCase();
2397
+ if (!q) return [...targets];
2398
+ return targets.filter(
2399
+ (t) => (t.number ?? "").toLowerCase().startsWith(q) || t.text.toLowerCase().includes(q)
2400
+ );
2401
+ }
2402
+
2403
+ // src/docx/references/commands.ts
2404
+ var REF_BOOKMARK_PREFIX = "_Ref";
2405
+ function newRefBookmark(taken, random = Math.random) {
2406
+ for (; ; ) {
2407
+ const name = `${REF_BOOKMARK_PREFIX}${String(Math.floor(random() * 9e8) + 1e8)}`;
2408
+ if (!taken.has(name)) return name;
2409
+ }
2410
+ }
2411
+ var styled = (style) => style ? `<w:rPr><w:rStyle w:val="${style}"/></w:rPr>` : "";
2412
+ var run = (text, style) => `<w:r>${styled(style)}<w:t xml:space="preserve">${chunk2A4MDHJR_cjs.esc(text)}</w:t></w:r>`;
2413
+ function refFieldXml(instruction, cached) {
2414
+ const r = (inner) => `<w:r>${styled(CROSS_REFERENCE_STYLE)}${inner}</w:r>`;
2415
+ return `${r('<w:fldChar w:fldCharType="begin"/>')}${r(
2416
+ `<w:instrText xml:space="preserve"> ${chunk2A4MDHJR_cjs.esc(instruction)} </w:instrText>`
2417
+ )}${r('<w:fldChar w:fldCharType="separate"/>')}${run(cached, CROSS_REFERENCE_STYLE)}${r(
2418
+ '<w:fldChar w:fldCharType="end"/>'
2419
+ )}`;
2420
+ }
2421
+ var refTooltip = (value, mode) => mode === "number" ? `Cross-reference to clause ${value}` : `Cross-reference to \u201C${value}\u201D`;
2422
+ function crossReferenceXml(bookmark, mode, value) {
2423
+ return `<w:hyperlink w:anchor="${chunk2A4MDHJR_cjs.esc(bookmark)}" w:tooltip="${chunk2A4MDHJR_cjs.esc(
2424
+ refTooltip(value, mode)
2425
+ )}" w:history="1">${refFieldXml(refInstruction(bookmark, mode), value)}</w:hyperlink>`;
2426
+ }
2427
+ var refInstruction = (bookmark, mode) => mode === "number" ? `REF ${bookmark} \\r \\h` : `REF ${bookmark} \\h`;
2428
+ var refResult = (target, mode) => mode === "number" && target.number ? target.number : target.text;
2429
+ var allBookmarks = (port) => new Set(port.paragraphs().flatMap((p) => p.bookmarks));
2430
+ function ensureTargetBookmark(port, target, mode) {
2431
+ const paragraph = port.paragraphs().find((p) => p.id === target.paragraphId);
2432
+ if (!paragraph) throw new Error("That clause is no longer in the document.");
2433
+ const existing = paragraph.bookmarks.find((b) => b.startsWith(REF_BOOKMARK_PREFIX));
2434
+ if (existing && mode === "number") return existing;
2435
+ const name = newRefBookmark(allBookmarks(port));
2436
+ const start = `<w:bookmarkStart w:id="0" w:name="${name}"/>`;
2437
+ const end = '<w:bookmarkEnd w:id="0"/>';
2438
+ if (mode === "number") {
2439
+ port.setCaret({ paragraphId: paragraph.id, offset: 0 });
2440
+ if (!port.paste(`<w:p>${start}${end}</w:p>`, "", false))
2441
+ throw new Error("The cross-reference target could not be marked.");
2442
+ return name;
2443
+ }
2444
+ const runs = port.runsXml(paragraph.id);
2445
+ if (!runs) throw new Error("This heading cannot be referred to by its text; use its number.");
2446
+ port.deleteRange(
2447
+ { paragraphId: paragraph.id, offset: 0 },
2448
+ { paragraphId: paragraph.id, offset: paragraph.text.length }
2449
+ );
2450
+ if (!port.paste(`<w:p>${start}${runs}${end}</w:p>`, paragraph.text, false))
2451
+ throw new Error("The cross-reference target could not be marked.");
2452
+ return name;
2453
+ }
2454
+ function pastePoint(port, caret) {
2455
+ const paragraph = port.paragraphs().find((p) => p.id === caret.paragraphId);
2456
+ if (paragraph?.text[caret.offset - 1] !== FIELD_ATOM) return caret;
2457
+ port.setCaret(caret);
2458
+ port.typeText(" ");
2459
+ return { paragraphId: caret.paragraphId, offset: caret.offset + 1 };
2460
+ }
2461
+ function markCrossReferenceTarget(port, target, mode) {
2462
+ if (mode === "number" && !target.number) mode = "text";
2463
+ const bookmark = ensureTargetBookmark(port, target, mode);
2464
+ return { bookmark, mode, value: refResult(target, mode) };
2465
+ }
2466
+ function insertCrossReferenceField(port, { bookmark, mode, value }, caret) {
2467
+ caret = pastePoint(port, caret);
2468
+ port.setCaret(caret);
2469
+ if (!port.paste(`<w:p>${crossReferenceXml(bookmark, mode, value)}</w:p>`, value, false))
2470
+ throw new Error("The cross-reference could not be inserted.");
2471
+ port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + 1 });
2472
+ return { bookmark };
2473
+ }
2474
+ function insertCrossReference(port, target, mode, caret) {
2475
+ return insertCrossReferenceField(port, markCrossReferenceTarget(port, target, mode), caret);
2476
+ }
2477
+ var documentReferenceTooltip = (text, appName = "ARBI") => `Cross-reference: ${text} \u2014 opens in ${appName}`;
2478
+ function insertDocumentReference(port, reference, caret) {
2479
+ const text = reference.text.trim();
2480
+ if (!text) throw new Error("Enter the reference text.");
2481
+ const tooltip = documentReferenceTooltip(text, reference.appName).slice(0, 255);
2482
+ caret = pastePoint(port, caret);
2483
+ port.setCaret(caret);
2484
+ const link = `<w:p><w:hyperlink r:id="rIdRef1"${tooltip ? ` w:tooltip="${chunk2A4MDHJR_cjs.esc(tooltip)}"` : ""} w:history="1">${run(text, CROSS_REFERENCE_STYLE)}</w:hyperlink></w:p>`;
2485
+ if (!port.paste(link, text, false, chunk2A4MDHJR_cjs.hyperlinkRelationship("rIdRef1", reference.url)))
2486
+ throw new Error("The reference could not be inserted.");
2487
+ port.setCaret({ paragraphId: caret.paragraphId, offset: caret.offset + text.length });
2488
+ }
2489
+ var REF_FIELD = /^REF\s+(\S+)((?:\s+\\[A-Za-z*]+(?:\s+MERGEFORMAT)?)*)\s*$/i;
2490
+ function staleCrossReferences(port) {
2491
+ const paragraphs = port.paragraphs();
2492
+ if (!paragraphs.some((p) => p.fields?.length)) return [];
2493
+ const items = port.listItems();
2494
+ const order = paragraphs.map((p) => p.id);
2495
+ const owner = /* @__PURE__ */ new Map();
2496
+ for (const p of paragraphs) for (const b of p.bookmarks) if (!owner.has(b)) owner.set(b, p.id);
2497
+ const out = [];
2498
+ for (const p of paragraphs)
2499
+ for (const field of p.fields ?? []) {
2500
+ const match = REF_FIELD.exec(field.instruction);
2501
+ if (!match || !match[1].startsWith(REF_BOOKMARK_PREFIX)) continue;
2502
+ const switches = match[2].toLowerCase();
2503
+ const mode = /\\[rwn]\b/.test(switches) ? "number" : "text";
2504
+ const target = owner.get(match[1]);
2505
+ const base = {
2506
+ paragraphId: p.id,
2507
+ offset: field.offset,
2508
+ instruction: field.instruction,
2509
+ cached: field.result,
2510
+ bookmark: match[1],
2511
+ mode
2512
+ };
2513
+ if (!target) {
2514
+ out.push({ ...base, value: null });
2515
+ continue;
2516
+ }
2517
+ 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();
2518
+ if (value && value !== field.result.trim()) out.push({ ...base, value });
2519
+ }
2520
+ return out;
2521
+ }
2522
+ function brokenCrossReferences(port) {
2523
+ return port.paragraphs().flatMap(
2524
+ (p) => (p.marks ?? []).filter((m) => m.styleId === BROKEN_CROSS_REFERENCE_STYLE).map((m) => ({ paragraphId: p.id, offset: m.offset, text: m.text }))
2525
+ );
2526
+ }
2527
+ function refreshCrossReferences(port) {
2528
+ const stale = staleCrossReferences(port).sort(
2529
+ (a, b) => a.paragraphId === b.paragraphId ? b.offset - a.offset : 0
2530
+ );
2531
+ let refreshed = 0;
2532
+ for (const ref of stale) {
2533
+ const paragraph = port.paragraphs().find((p) => p.id === ref.paragraphId);
2534
+ if (!paragraph || paragraph.text[ref.offset - 1] === FIELD_ATOM) continue;
2535
+ const at = { paragraphId: ref.paragraphId, offset: ref.offset };
2536
+ port.deleteRange(at, { paragraphId: ref.paragraphId, offset: ref.offset + 1 });
2537
+ port.setCaret(at);
2538
+ const text = ref.value ?? (ref.cached.trim() || ref.bookmark);
2539
+ const body = ref.value === null ? run(text, BROKEN_CROSS_REFERENCE_STYLE) : crossReferenceXml(ref.bookmark, ref.mode, ref.value);
2540
+ if (port.paste(`<w:p>${body}</w:p>`, text, false) && ref.value !== null) refreshed++;
2541
+ }
2542
+ return { refreshed, broken: brokenCrossReferences(port) };
2543
+ }
2544
+
2545
+ // src/docx/references/passages.ts
2546
+ function shortTitle(title) {
2547
+ const base = title.replace(/\.[A-Za-z0-9]{1,5}$/, "").trim();
2548
+ const defined = /\(\s*(?:the\s+)?["“'‘]([^"”'’]{1,30})["”'’]\s*\)/i.exec(base);
2549
+ return defined ? defined[1] : base;
2550
+ }
2551
+ function passageClause(text) {
2552
+ const first = text.trim().split("\n")[0] ?? "";
2553
+ const match = /^(?:#+\s*)?(?:\*\*)?(?:clause|section|article)?\s*(\d+(?:\.\d+)*)[.)]?(?:\*\*)?\s+\S/i.exec(
2554
+ first
2555
+ );
2556
+ return match ? match[1] : null;
2557
+ }
2558
+ function referenceText(title, passage) {
2559
+ const name = shortTitle(title);
2560
+ const clause = passageClause(passage.text);
2561
+ if (clause) return `${name}, clause ${clause}`;
2562
+ if (passage.page) return `${name}, p. ${passage.page}`;
2563
+ return name;
2564
+ }
2565
+ function passageExcerpt(text, max = 280) {
2566
+ const plain = text.replace(/[#*_`>|]+/g, " ").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\s+/g, " ").trim();
2567
+ return plain.length > max ? `${plain.slice(0, max - 1)}\u2026` : plain;
2568
+ }
2569
+ function filterPassages(passages, query) {
2570
+ const q = query.trim().toLowerCase();
2571
+ return q ? passages.filter((p) => p.text.toLowerCase().includes(q)) : [...passages];
2572
+ }
2573
+ var RUN_PARTS = /* @__PURE__ */ new Set(["rPr", "t", "tab", "br", "lastRenderedPageBreak"]);
2574
+ var SKIPPED = /* @__PURE__ */ new Set(["pPr", "bookmarkStart", "bookmarkEnd", "proofErr", "permStart", "permEnd"]);
2575
+ function serialize(node) {
2576
+ if (node.kind === "textValue") return chunk2A4MDHJR_cjs.esc(node.value ?? "");
2577
+ const name = `${node.prefix ?? "w"}:${node.localName}`;
2578
+ const attrs = (node.attributes ?? []).map((a) => ` ${a.prefix ? `${a.prefix}:` : ""}${a.localName}="${chunk2A4MDHJR_cjs.esc(a.value)}"`).join("");
2579
+ const children = (node.children ?? []).map((c) => serialize(c)).join("");
2580
+ return children ? `<${name}${attrs}>${children}</${name}>` : `<${name}${attrs}/>`;
2581
+ }
2582
+ function paragraphRunsXml(paragraph) {
2583
+ const runs = [];
2584
+ for (const child of paragraph.children ?? []) {
2585
+ if (child.localName && SKIPPED.has(child.localName)) continue;
2586
+ if (child.localName !== "r") return null;
2587
+ if ((child.children ?? []).some((c) => !c.localName || !RUN_PARTS.has(c.localName))) return null;
2588
+ runs.push(serialize(child));
2589
+ }
2590
+ return runs.length ? runs.join("") : null;
2591
+ }
2592
+ function findNode2(node, id) {
2593
+ if (node.id === id) return node;
2594
+ for (const child of node.children ?? []) {
2595
+ const found = findNode2(child, id);
2596
+ if (found) return found;
2597
+ }
2598
+ return void 0;
2599
+ }
2600
+ function referencesPort(editor, revision) {
2601
+ const base = editorPort(editor, revision);
2602
+ const session = () => {
2603
+ const s = editor.surface?.session;
2604
+ if (!s) throw new Error("The document is not open.");
2605
+ return s;
2606
+ };
2607
+ const root = () => session().part().root;
2608
+ let numbering;
2609
+ let cascade;
2610
+ const index = () => {
2611
+ if (!numbering) {
2612
+ const s = session();
2613
+ cascade = layout.buildStyleCascadeTable(s.stylesRoot(), void 0, s.settingsRoot());
2614
+ numbering = layout.withNumberingStyleLinks(layout.buildNumberingIndex(s.numberingRoot()), cascade);
2615
+ }
2616
+ return numbering;
2617
+ };
2618
+ return {
2619
+ ...base,
2620
+ listItems: () => {
2621
+ const body = root().children?.find((n) => n.kind === "body");
2622
+ const items = layout.resolveStoryListItems(
2623
+ body?.children ?? [],
2624
+ index(),
2625
+ cascade
2626
+ );
2627
+ const out = /* @__PURE__ */ new Map();
2628
+ for (const [id, item] of items)
2629
+ out.set(id, {
2630
+ numId: item.numId,
2631
+ ilvl: item.ilvl,
2632
+ markerText: item.markerText,
2633
+ numFmt: item.numFmt
2634
+ });
2635
+ return out;
2636
+ },
2637
+ levelOf: (numId, ilvl) => {
2638
+ const level = layout.resolveNumberingLevel(index(), numId, ilvl)?.level;
2639
+ return level ? { lvlText: level.lvlText, numFmt: level.numFmt } : null;
2640
+ },
2641
+ runsXml: (paragraphId) => {
2642
+ const node = findNode2(root(), paragraphId);
2643
+ return node ? paragraphRunsXml(node) : null;
2644
+ }
2645
+ };
2646
+ }
2647
+
2648
+ // src/docx/beforeSave.ts
2649
+ var hooks = /* @__PURE__ */ new WeakMap();
2650
+ function onBeforeSave(editor, fn) {
2651
+ let set = hooks.get(editor);
2652
+ if (!set) hooks.set(editor, set = /* @__PURE__ */ new Set());
2653
+ set.add(fn);
2654
+ return () => set.delete(fn);
2655
+ }
2656
+ function runBeforeSave(editor) {
2657
+ if (!editor) return;
2658
+ for (const fn of hooks.get(editor) ?? [])
2659
+ try {
2660
+ fn();
2661
+ } catch {
2662
+ }
2663
+ }
2664
+ var DEFAULT_CROSS_REFERENCES_LABELS = {
2665
+ insert: "Insert cross-reference",
2666
+ title: "Insert cross-reference",
2667
+ description: "Refer to a clause of this document, or to a passage of another document.",
2668
+ thisDocument: "This document",
2669
+ otherDocument: "Another document",
2670
+ filterTargets: "Find a clause or heading",
2671
+ noTargets: "This document has no numbered clauses or headings yet.",
2672
+ number: "Paragraph number",
2673
+ text: "Heading text",
2674
+ insertAs: "Insert",
2675
+ chooseDocument: "Choose a document",
2676
+ filterPassages: "Find a passage",
2677
+ loadingPassages: "Loading passages\u2026",
2678
+ noPassages: "No passage matches.",
2679
+ referenceText: "Reference text",
2680
+ insertButton: "Insert",
2681
+ cancel: "Cancel",
2682
+ clause: (number) => `Clause ${number}`,
2683
+ heading: "Heading",
2684
+ update: "Update cross-references",
2685
+ updated: "Cross-references updated",
2686
+ updateSummary: (refreshed) => refreshed ? `${refreshed} cross-reference${refreshed === 1 ? "" : "s"} brought up to date.` : "Every cross-reference is up to date.",
2687
+ brokenTitle: "Broken cross-references",
2688
+ brokenNone: "No cross-reference points at a deleted target.",
2689
+ brokenHelp: "Their target was deleted: the last text is kept and marked. Insert the reference again to repair it.",
2690
+ brokenCard: "Broken cross-reference",
2691
+ brokenCardBody: "Its target was deleted. Update cross-references to mark it.",
2692
+ show: "Show",
2693
+ close: "Close"
2694
+ };
2695
+ var CrossReferencesContext = React4.createContext(null);
2696
+ var useCrossReferences = () => React4.useContext(CrossReferencesContext);
2697
+ function CrossReferencesProvider({
2698
+ children,
2699
+ editable,
2700
+ references,
2701
+ documentId,
2702
+ notify,
2703
+ labels
2704
+ }) {
2705
+ const editor = react.useDocxEditor();
2706
+ const track = useTrackedOrNoted();
2707
+ const l = React4.useMemo(() => ({ ...DEFAULT_CROSS_REFERENCES_LABELS, ...labels }), [labels]);
2708
+ const [dialog, setDialog] = React4.useState(
2709
+ null
2710
+ );
2711
+ const marker = React4.useRef(null);
2712
+ const [viewer, setViewer] = React4.useState(null);
2713
+ React4.useEffect(() => setViewer(marker.current?.closest(".native-docx-viewer") ?? null), []);
2714
+ const openDialog = React4.useCallback(() => {
2715
+ if (!editor || !editable) return;
2716
+ try {
2717
+ const port = referencesPort(editor);
2718
+ const caret = port.caret();
2719
+ if (!caret) return notify?.("Place the cursor where the reference should go.", "error");
2720
+ setDialog({ caret, targets: listTargets(port.paragraphs(), port.listItems(), port.levelOf) });
2721
+ } catch (error) {
2722
+ notify?.(error instanceof Error ? error.message : "Could not read the document.", "error");
2723
+ }
2724
+ }, [editor, editable, notify]);
2725
+ const run2 = React4.useCallback(
2726
+ (label, prepare, insert) => {
2727
+ if (!editor) return;
2728
+ try {
2729
+ const prepared = withDirectEditing(editor, prepare);
2730
+ if (dialog) referencesPort(editor).setCaret(dialog.caret);
2731
+ track({ label, insert: (revision) => insert(prepared, revision), inserted: () => true });
2732
+ setDialog(null);
2733
+ editor.surface?.focus();
2734
+ holdCaret(editor);
2735
+ } catch (error) {
2736
+ notify?.(
2737
+ error instanceof Error ? error.message : "Could not insert the reference.",
2738
+ "error"
2739
+ );
2740
+ }
2741
+ },
2742
+ [editor, dialog, track, notify]
2743
+ );
2744
+ React4.useEffect(() => {
2745
+ if (!editor || !editable) return;
2746
+ const refresh = () => {
2747
+ try {
2748
+ const port = referencesPort(editor);
2749
+ if (!port.paragraphs().some((p) => p.fields?.length)) return;
2750
+ preservingCaret(editor, () => withDirectEditing(editor, () => refreshCrossReferences(port)));
2751
+ } catch {
2752
+ }
2753
+ };
2754
+ const off = onBeforeSave(editor, refresh);
2755
+ const timer = setTimeout(refresh, 1500);
2756
+ return () => {
2757
+ off();
2758
+ clearTimeout(timer);
2759
+ };
2760
+ }, [editor, editable]);
2761
+ const [report, setReport] = React4.useState(null);
2762
+ const update = React4.useCallback(() => {
2763
+ if (!editor || !editable) return;
2764
+ try {
2765
+ const result = preservingCaret(
2766
+ editor,
2767
+ () => withDirectEditing(editor, () => refreshCrossReferences(referencesPort(editor)))
2768
+ );
2769
+ setReport(result);
2770
+ } catch (error) {
2771
+ notify?.(
2772
+ error instanceof Error ? error.message : "Could not update cross-references.",
2773
+ "error"
2774
+ );
2775
+ }
2776
+ }, [editor, editable, notify]);
2777
+ const [passages, setPassages] = React4.useState({});
2778
+ const loadPassages = React4.useCallback(
2779
+ (id) => {
2780
+ if (!references || passages[id]) return;
2781
+ setPassages((p) => ({ ...p, [id]: "loading" }));
2782
+ references.passages(id).then((list) => setPassages((p) => ({ ...p, [id]: list }))).catch(() => setPassages((p) => ({ ...p, [id]: [] })));
2783
+ },
2784
+ [references, passages]
2785
+ );
2786
+ React4.useEffect(() => {
2787
+ if (!viewer || !references) return;
2788
+ const targetOf = (event) => {
2789
+ const link = event.target?.closest?.(
2790
+ 'a.docx-hyperlink[data-docx-link-kind="external"]'
2791
+ );
2792
+ if (!link || !viewer.contains(link)) return null;
2793
+ const mouse = event;
2794
+ if (mouse.button !== 0 || mouse.ctrlKey || mouse.metaKey || mouse.shiftKey) return null;
2795
+ return references.targetOf(link.getAttribute("href") ?? "");
2796
+ };
2797
+ const take = (event) => {
2798
+ const target = targetOf(event);
2799
+ if (!target) return;
2800
+ event.preventDefault();
2801
+ event.stopPropagation();
2802
+ if (event.type === "click") references.open(target);
2803
+ };
2804
+ const types = ["pointerdown", "mousedown", "pointerup", "mouseup", "click"];
2805
+ for (const type of types) window.addEventListener(type, take, true);
2806
+ return () => {
2807
+ for (const type of types) window.removeEventListener(type, take, true);
2808
+ };
2809
+ }, [viewer, references]);
2810
+ const value = React4.useMemo(
2811
+ () => editable ? { openDialog, update, labels: l } : null,
2812
+ [editable, openDialog, update, l]
2813
+ );
2814
+ const resolveInternal = (href) => {
2815
+ if (!editor) return null;
2816
+ const name = href.replace(/^#/, "");
2817
+ try {
2818
+ const port = referencesPort(editor);
2819
+ const paragraphs = port.paragraphs();
2820
+ const target = paragraphs.find((p) => p.bookmarks.includes(name));
2821
+ if (!target) return { title: l.brokenCard, body: l.brokenCardBody };
2822
+ const number = paragraphNumber(
2823
+ paragraphs.map((p) => p.id),
2824
+ port.listItems(),
2825
+ port.levelOf,
2826
+ target.id
2827
+ );
2828
+ return {
2829
+ title: number ? l.clause(number) : l.heading,
2830
+ body: passageExcerpt(target.text.replace(//g, ""))
2831
+ };
2832
+ } catch {
2833
+ return null;
2834
+ }
2835
+ };
2836
+ return /* @__PURE__ */ jsxRuntime.jsxs(CrossReferencesContext.Provider, { value, children: [
2837
+ /* @__PURE__ */ jsxRuntime.jsx("span", { ref: marker, hidden: true }),
2838
+ children,
2839
+ /* @__PURE__ */ jsxRuntime.jsx(
2840
+ LinkHoverCard,
2841
+ {
2842
+ root: viewer,
2843
+ matches: (href) => href.startsWith(`#${REF_BOOKMARK_PREFIX}`),
2844
+ resolve: resolveInternal,
2845
+ testId: "docx-cross-reference-card"
2846
+ }
2847
+ ),
2848
+ references && /* @__PURE__ */ jsxRuntime.jsx(
2849
+ LinkHoverCard,
2850
+ {
2851
+ root: viewer,
2852
+ matches: (href) => !!references.targetOf(href),
2853
+ resolve: (href) => {
2854
+ const target = references.targetOf(href);
2855
+ if (!target) return null;
2856
+ const list = passages[target.documentId];
2857
+ if (!list) loadPassages(target.documentId);
2858
+ const passage = Array.isArray(list) ? list.find((p) => p.chunkId === target.chunkId) : void 0;
2859
+ return passage ? {
2860
+ body: passageExcerpt(passage.text),
2861
+ footer: passage.page ? `p. ${passage.page}` : void 0
2862
+ } : null;
2863
+ },
2864
+ testId: "docx-cross-reference-card"
2865
+ }
2866
+ ),
2867
+ dialog && /* @__PURE__ */ jsxRuntime.jsx(
2868
+ CrossReferenceDialog,
2869
+ {
2870
+ targets: dialog.targets,
2871
+ references,
2872
+ documentId,
2873
+ passages,
2874
+ loadPassages,
2875
+ labels: l,
2876
+ onCancel: () => setDialog(null),
2877
+ onClosed: () => editor?.surface?.focus(),
2878
+ onInsertTarget: (target, mode) => run2(
2879
+ `Inserted cross-reference: ${refResult(target, mode)}`,
2880
+ () => markCrossReferenceTarget(referencesPort(editor), target, mode),
2881
+ (marked, revision) => insertCrossReferenceField(referencesPort(editor, revision), marked, dialog.caret)
2882
+ ),
2883
+ onInsertPassage: (target, text) => run2(
2884
+ `Inserted cross-reference: ${text}`,
2885
+ () => void 0,
2886
+ (_, revision) => insertDocumentReference(
2887
+ referencesPort(editor, revision),
2888
+ { text, url: references.linkFor(target), appName: references.appName },
2889
+ dialog.caret
2890
+ )
2891
+ )
2892
+ }
2893
+ ),
2894
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open: !!report, onOpenChange: (open) => !open && setReport(null), children: /* @__PURE__ */ jsxRuntime.jsxs(
2895
+ ui.DialogContent,
2896
+ {
2897
+ className: "max-h-[85dvh] overflow-y-auto",
2898
+ "data-testid": "docx-cross-references-report",
2899
+ children: [
2900
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogHeader, { children: [
2901
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DialogTitle, { children: l.updated }),
2902
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DialogDescription, { children: report && l.updateSummary(report.refreshed) })
2903
+ ] }),
2904
+ report && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-1 text-sm", children: [
2905
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-medium", children: l.brokenTitle }),
2906
+ report.broken.length ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2907
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: l.brokenHelp }),
2908
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", "data-testid": "docx-cross-references-broken", children: report.broken.map((b) => /* @__PURE__ */ jsxRuntime.jsxs(
2909
+ "li",
2910
+ {
2911
+ className: "flex items-center justify-between gap-2",
2912
+ children: [
2913
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-text", children: b.text }),
2914
+ /* @__PURE__ */ jsxRuntime.jsx(
2915
+ ui.Button,
2916
+ {
2917
+ size: "sm",
2918
+ variant: "ghost",
2919
+ onClick: () => {
2920
+ const point = { paragraphId: b.paragraphId, offset: b.offset };
2921
+ editor?.surface?.setSelection({ anchor: point, head: point });
2922
+ editor?.surface?.revealParagraph(b.paragraphId);
2923
+ setReport(null);
2924
+ },
2925
+ children: l.show
2926
+ }
2927
+ )
2928
+ ]
2929
+ },
2930
+ `${b.paragraphId}:${b.offset}`
2931
+ )) })
2932
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: l.brokenNone })
2933
+ ] }),
2934
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "outline", onClick: () => setReport(null), children: l.close }) })
2935
+ ]
2936
+ }
2937
+ ) })
2938
+ ] });
2939
+ }
2940
+ function CrossReferenceDialog({
2941
+ targets,
2942
+ references,
2943
+ documentId,
2944
+ passages,
2945
+ loadPassages,
2946
+ labels,
2947
+ onCancel,
2948
+ onInsertTarget,
2949
+ onInsertPassage,
2950
+ onClosed
2951
+ }) {
2952
+ const l = { ...DEFAULT_CROSS_REFERENCES_LABELS, ...labels };
2953
+ const [tab, setTab] = React4.useState("this");
2954
+ const [query, setQuery] = React4.useState("");
2955
+ const [chosen, setChosen] = React4.useState(null);
2956
+ const [mode, setMode] = React4.useState("number");
2957
+ const shown = React4.useMemo(() => filterTargets(targets, query), [targets, query]);
2958
+ const effectiveMode = chosen?.number ? mode : "text";
2959
+ const [documents, setDocuments] = React4.useState(null);
2960
+ const [docId, setDocId] = React4.useState(null);
2961
+ const [passageQuery, setPassageQuery] = React4.useState("");
2962
+ const [passage, setPassage] = React4.useState(null);
2963
+ const [text, setText] = React4.useState("");
2964
+ React4.useEffect(() => {
2965
+ if (tab !== "other" || !references || documents) return;
2966
+ references.documents().then((list2) => setDocuments(list2.filter((d) => d.id !== documentId))).catch(() => setDocuments([]));
2967
+ }, [tab, references, documents, documentId]);
2968
+ const chooseDocument = (id) => {
2969
+ setDocId(id);
2970
+ setPassage(null);
2971
+ setText("");
2972
+ loadPassages(id);
2973
+ };
2974
+ const title = documents?.find((d) => d.id === docId)?.title ?? "";
2975
+ const list = docId ? passages[docId] : void 0;
2976
+ const shownPassages = Array.isArray(list) ? filterPassages(list, passageQuery) : [];
2977
+ const canInsert = tab === "this" ? !!chosen : !!(docId && passage && text.trim());
2978
+ const insert = () => {
2979
+ if (tab === "this" && chosen) onInsertTarget(chosen, effectiveMode);
2980
+ if (tab === "other" && docId && passage)
2981
+ onInsertPassage(
2982
+ { documentId: docId, chunkId: passage.chunkId, page: passage.page ?? null },
2983
+ text
2984
+ );
2985
+ };
2986
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open: true, onOpenChange: (open) => !open && onCancel(), children: /* @__PURE__ */ jsxRuntime.jsxs(
2987
+ ui.DialogContent,
2988
+ {
2989
+ className: "max-h-[85dvh] overflow-y-auto",
2990
+ "data-testid": "docx-cross-reference-dialog",
2991
+ onCloseAutoFocus: (event) => {
2992
+ if (!onClosed) return;
2993
+ event.preventDefault();
2994
+ onClosed();
2995
+ },
2996
+ children: [
2997
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogHeader, { children: [
2998
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DialogTitle, { children: l.title }),
2999
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DialogDescription, { children: l.description })
3000
+ ] }),
3001
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs, { value: tab, onValueChange: (v) => setTab(v), children: [
3002
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TabsList, { children: [
3003
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TabsTrigger, { value: "this", "data-testid": "docx-cross-reference-this", children: l.thisDocument }),
3004
+ references && /* @__PURE__ */ jsxRuntime.jsx(ui.TabsTrigger, { value: "other", "data-testid": "docx-cross-reference-other", children: l.otherDocument })
3005
+ ] }),
3006
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TabsContent, { value: "this", className: "space-y-3", children: [
3007
+ /* @__PURE__ */ jsxRuntime.jsx(
3008
+ ui.Input,
3009
+ {
3010
+ value: query,
3011
+ placeholder: l.filterTargets,
3012
+ "aria-label": l.filterTargets,
3013
+ onChange: (e) => setQuery(e.target.value),
3014
+ "data-testid": "docx-cross-reference-filter"
3015
+ }
3016
+ ),
3017
+ /* @__PURE__ */ jsxRuntime.jsxs(
3018
+ "div",
3019
+ {
3020
+ role: "listbox",
3021
+ "aria-label": l.filterTargets,
3022
+ className: "max-h-64 space-y-0.5 overflow-y-auto rounded-md border border-border p-1",
3023
+ children: [
3024
+ shown.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-2 text-sm text-muted-foreground", children: l.noTargets }),
3025
+ shown.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
3026
+ "button",
3027
+ {
3028
+ type: "button",
3029
+ role: "option",
3030
+ "aria-selected": chosen?.paragraphId === t.paragraphId,
3031
+ "data-testid": "docx-cross-reference-target",
3032
+ onClick: () => setChosen(t),
3033
+ onDoubleClick: () => onInsertTarget(t, t.number ? mode : "text"),
3034
+ className: ui.cn(
3035
+ "flex w-full items-baseline gap-2 rounded px-2 py-1 text-left text-sm",
3036
+ chosen?.paragraphId === t.paragraphId ? "bg-accent" : "hover:bg-accent/50"
3037
+ ),
3038
+ style: { paddingLeft: 8 + t.level * 16 },
3039
+ children: [
3040
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: t.marker || l.heading }),
3041
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.cn("truncate", t.heading && "font-medium"), children: t.text })
3042
+ ]
3043
+ },
3044
+ t.paragraphId
3045
+ ))
3046
+ ]
3047
+ }
3048
+ ),
3049
+ chosen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3 text-sm", children: [
3050
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: l.insertAs }),
3051
+ chosen.number && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-1", children: [
3052
+ /* @__PURE__ */ jsxRuntime.jsx(
3053
+ "input",
3054
+ {
3055
+ type: "radio",
3056
+ name: "cross-reference-mode",
3057
+ checked: effectiveMode === "number",
3058
+ onChange: () => setMode("number")
3059
+ }
3060
+ ),
3061
+ l.number
3062
+ ] }),
3063
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-1", children: [
3064
+ /* @__PURE__ */ jsxRuntime.jsx(
3065
+ "input",
3066
+ {
3067
+ type: "radio",
3068
+ name: "cross-reference-mode",
3069
+ checked: effectiveMode === "text",
3070
+ onChange: () => setMode("text")
3071
+ }
3072
+ ),
3073
+ l.text
3074
+ ] }),
3075
+ /* @__PURE__ */ jsxRuntime.jsx(
3076
+ "span",
3077
+ {
3078
+ className: "ml-auto rounded bg-muted px-2 py-0.5",
3079
+ "data-testid": "docx-cross-reference-preview",
3080
+ children: refResult(chosen, effectiveMode)
3081
+ }
3082
+ )
3083
+ ] })
3084
+ ] }),
3085
+ references && /* @__PURE__ */ jsxRuntime.jsxs(ui.TabsContent, { value: "other", className: "space-y-3", children: [
3086
+ references.renderDocumentPicker ? references.renderDocumentPicker(chooseDocument, docId) : /* @__PURE__ */ jsxRuntime.jsxs(
3087
+ "select",
3088
+ {
3089
+ className: "h-9 w-full rounded-md border border-border bg-background px-2 text-sm",
3090
+ "aria-label": l.chooseDocument,
3091
+ value: docId ?? "",
3092
+ onChange: (e) => e.target.value && chooseDocument(e.target.value),
3093
+ "data-testid": "docx-cross-reference-document",
3094
+ children: [
3095
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: l.chooseDocument }),
3096
+ (documents ?? []).map((d) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: d.id, children: d.title }, d.id))
3097
+ ]
3098
+ }
3099
+ ),
3100
+ docId && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3101
+ /* @__PURE__ */ jsxRuntime.jsx(
3102
+ ui.Input,
3103
+ {
3104
+ value: passageQuery,
3105
+ placeholder: l.filterPassages,
3106
+ "aria-label": l.filterPassages,
3107
+ onChange: (e) => setPassageQuery(e.target.value),
3108
+ "data-testid": "docx-cross-reference-passage-filter"
3109
+ }
3110
+ ),
3111
+ /* @__PURE__ */ jsxRuntime.jsx(
3112
+ "div",
3113
+ {
3114
+ className: "max-h-64 space-y-1 overflow-y-auto",
3115
+ "data-testid": "docx-cross-reference-passages",
3116
+ children: list === "loading" || list === void 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-2 text-sm text-muted-foreground", children: l.loadingPassages }) : shownPassages.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-2 text-sm text-muted-foreground", children: l.noPassages }) : shownPassages.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
3117
+ chunk5FYU7ZIU_cjs.FactPassageItem,
3118
+ {
3119
+ index: i,
3120
+ page: p.page,
3121
+ excerpt: passageExcerpt(p.text, 200),
3122
+ isViewing: passage?.chunkId === p.chunkId,
3123
+ onSelect: () => {
3124
+ setPassage(p);
3125
+ setText(referenceText(title, p));
3126
+ },
3127
+ testId: "docx-cross-reference-passage"
3128
+ },
3129
+ p.chunkId
3130
+ ))
3131
+ }
3132
+ ),
3133
+ passage && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block space-y-1 text-sm", children: [
3134
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: l.referenceText }),
3135
+ /* @__PURE__ */ jsxRuntime.jsx(
3136
+ ui.Input,
3137
+ {
3138
+ value: text,
3139
+ onChange: (e) => setText(e.target.value),
3140
+ "data-testid": "docx-cross-reference-text"
3141
+ }
3142
+ )
3143
+ ] })
3144
+ ] })
3145
+ ] })
3146
+ ] }),
3147
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogFooter, { children: [
3148
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "outline", onClick: onCancel, children: l.cancel }),
3149
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { disabled: !canInsert, onClick: insert, "data-testid": "docx-cross-reference-insert", children: l.insertButton })
3150
+ ] })
3151
+ ]
3152
+ }
3153
+ ) });
3154
+ }
2191
3155
  function RibbonMenu({
2192
3156
  label,
2193
3157
  icon,
2194
3158
  children,
2195
3159
  className,
2196
3160
  testId,
2197
- title
3161
+ title,
3162
+ keepMounted = false,
3163
+ popoverClassName
2198
3164
  }) {
2199
- const [open, setOpen] = React3.useState(false);
2200
- const element = React3.useRef(null);
2201
- React3.useEffect(() => {
3165
+ const [open, setOpen] = React4.useState(false);
3166
+ const element = React4.useRef(null);
3167
+ React4.useEffect(() => {
2202
3168
  if (!open) return;
2203
3169
  const dismiss = (event) => {
2204
3170
  if (!element.current?.contains(event.target)) setOpen(false);
@@ -2228,12 +3194,13 @@ function RibbonMenu({
2228
3194
  children: icon
2229
3195
  }
2230
3196
  ),
2231
- open && /* @__PURE__ */ jsxRuntime.jsx(
3197
+ (open || keepMounted) && /* @__PURE__ */ jsxRuntime.jsx(
2232
3198
  "div",
2233
3199
  {
2234
- className: "native-docx-ribbon-popover",
3200
+ className: ["native-docx-ribbon-popover", popoverClassName].filter(Boolean).join(" "),
2235
3201
  role: "group",
2236
3202
  "aria-label": label,
3203
+ hidden: !open,
2237
3204
  onMouseDown: (event) => {
2238
3205
  if (!(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement))
2239
3206
  event.preventDefault();
@@ -2306,7 +3273,7 @@ var AUTO = "";
2306
3273
  function useGenerateImageTarget() {
2307
3274
  const editor = react.useDocxEditor();
2308
3275
  const loaded2 = react.useEditorState((snapshot) => !snapshot.isLoading);
2309
- React3.useEffect(() => {
3276
+ React4.useEffect(() => {
2310
3277
  if (!editor || !loaded2) return;
2311
3278
  mounted.push(editor);
2312
3279
  return () => void mounted.splice(mounted.indexOf(editor), 1);
@@ -2314,16 +3281,16 @@ function useGenerateImageTarget() {
2314
3281
  }
2315
3282
  function GenerateImageButton({ generation }) {
2316
3283
  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(() => {
3284
+ const [prompt, setPrompt] = React4.useState("");
3285
+ const [aspectRatio, setAspectRatio] = React4.useState(AUTO);
3286
+ const [busy, setBusy] = React4.useState(false);
3287
+ const [error, setError] = React4.useState("");
3288
+ const abort = React4.useRef(null);
3289
+ const close = React4.useRef(() => {
2323
3290
  });
2324
3291
  const editable = react.useEditorState((snapshot) => snapshot.editable);
2325
- const generating = React3.useSyncExternalStore(subscribe, () => running > 0);
2326
- async function run() {
3292
+ const generating = React4.useSyncExternalStore(subscribe, () => running > 0);
3293
+ async function run2() {
2327
3294
  if (!editor || !prompt.trim() || busy) return;
2328
3295
  const caret = rememberCaret(editor);
2329
3296
  const controller = new AbortController();
@@ -2369,7 +3336,7 @@ function GenerateImageButton({ generation }) {
2369
3336
  className: "native-docx-form native-docx-generate-image",
2370
3337
  onSubmit: (event) => {
2371
3338
  event.preventDefault();
2372
- void run();
3339
+ void run2();
2373
3340
  },
2374
3341
  children: [
2375
3342
  /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
@@ -2385,7 +3352,7 @@ function GenerateImageButton({ generation }) {
2385
3352
  "data-testid": "docx-generate-image-prompt",
2386
3353
  onChange: (event) => setPrompt(event.target.value),
2387
3354
  onKeyDown: (event) => {
2388
- if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) void run();
3355
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) void run2();
2389
3356
  }
2390
3357
  }
2391
3358
  )
@@ -2511,6 +3478,163 @@ var WordDraftStream = class {
2511
3478
  }
2512
3479
  };
2513
3480
 
3481
+ // src/docx/overflowPlan.ts
3482
+ function planOverflow(items, available, moreWidth) {
3483
+ const collapsed = /* @__PURE__ */ new Set();
3484
+ let used = items.reduce((sum, item) => sum + item.width, 0);
3485
+ if (used <= available) return collapsed;
3486
+ used += moreWidth;
3487
+ const order = items.map((item, index) => ({ item, index })).sort((a, b) => a.item.priority - b.item.priority || b.index - a.index);
3488
+ for (const { item } of order) {
3489
+ if (used <= available) break;
3490
+ collapsed.add(item.id);
3491
+ used -= item.width;
3492
+ }
3493
+ return collapsed;
3494
+ }
3495
+ var Overflow = React4.createContext(null);
3496
+ var MORE_WIDTH = 32;
3497
+ var sameSet = (a, b) => a.size === b.size && [...a].every((id) => b.has(id));
3498
+ function RibbonOverflow({ tab, children }) {
3499
+ const row = React4.useRef(null);
3500
+ const items = React4.useRef(/* @__PURE__ */ new Map());
3501
+ const widths = React4.useRef(/* @__PURE__ */ new Map());
3502
+ const [version, setVersion] = React4.useState(0);
3503
+ const [collapsed, setCollapsed] = React4.useState(() => /* @__PURE__ */ new Set());
3504
+ const [slots, setSlots] = React4.useState({});
3505
+ const [menu, setMenu] = React4.useState([]);
3506
+ const register = React4.useCallback((id, item) => {
3507
+ items.current.set(id, item);
3508
+ setVersion((v) => v + 1);
3509
+ return () => {
3510
+ if (items.current.get(id) === item) items.current.delete(id);
3511
+ setVersion((v) => v + 1);
3512
+ };
3513
+ }, []);
3514
+ const plan = React4.useCallback(() => {
3515
+ const element = row.current;
3516
+ if (!element) return;
3517
+ const gap = parseFloat(getComputedStyle(element).columnGap) || 0;
3518
+ const ordered = Array.from(element.querySelectorAll("[data-ribbon-item]")).map((node) => node.dataset.ribbonItem).filter((id) => items.current.has(id));
3519
+ const measured = ordered.map((id) => {
3520
+ const { element: node, priority } = items.current.get(id);
3521
+ if (!node.hidden) {
3522
+ const width = node.getBoundingClientRect().width;
3523
+ widths.current.set(id, width ? width + gap : 0);
3524
+ }
3525
+ return { id, priority, width: widths.current.get(id) ?? 0 };
3526
+ });
3527
+ const next = planOverflow(measured, element.clientWidth, MORE_WIDTH);
3528
+ setCollapsed((current) => sameSet(current, next) ? current : next);
3529
+ const entries = ordered.filter((id) => next.has(id)).map((id) => ({ id, label: items.current.get(id).label }));
3530
+ setMenu(
3531
+ (current) => current.length === entries.length && current.every((entry, i) => entry.id === entries[i].id && entry.label === entries[i].label) ? current : entries
3532
+ );
3533
+ }, []);
3534
+ React4.useLayoutEffect(plan, [plan, version, tab, collapsed]);
3535
+ React4.useLayoutEffect(() => {
3536
+ const element = row.current;
3537
+ if (!element) return;
3538
+ const observer = new ResizeObserver(() => plan());
3539
+ observer.observe(element);
3540
+ for (const item of items.current.values()) observer.observe(item.element);
3541
+ return () => observer.disconnect();
3542
+ }, [plan, version]);
3543
+ const slotRef = React4.useCallback(
3544
+ (id) => (node) => setSlots((current) => {
3545
+ if (node ? current[id] === node : !(id in current)) return current;
3546
+ const next = { ...current };
3547
+ if (node) next[id] = node;
3548
+ else delete next[id];
3549
+ return next;
3550
+ }),
3551
+ []
3552
+ );
3553
+ const context = React4.useMemo(() => ({ collapsed, slots, register }), [collapsed, slots, register]);
3554
+ const shown = menu.filter((entry) => collapsed.has(entry.id));
3555
+ return /* @__PURE__ */ jsxRuntime.jsx(Overflow.Provider, { value: context, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-ribbon-row", ref: row, "data-testid": "docx-ribbon-row", children: [
3556
+ children,
3557
+ shown.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
3558
+ RibbonMenu,
3559
+ {
3560
+ label: "More",
3561
+ title: "More commands",
3562
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { size: 16 }),
3563
+ testId: "docx-ribbon-more",
3564
+ keepMounted: true,
3565
+ popoverClassName: "native-docx-ribbon-more",
3566
+ children: (close) => /* @__PURE__ */ jsxRuntime.jsx(MoreRows, { entries: shown, slotRef, close })
3567
+ },
3568
+ tab
3569
+ )
3570
+ ] }) });
3571
+ }
3572
+ function MoreRows({
3573
+ entries,
3574
+ slotRef,
3575
+ close
3576
+ }) {
3577
+ const refs = React4.useRef(/* @__PURE__ */ new Map());
3578
+ const refFor = (id) => {
3579
+ let ref = refs.current.get(id);
3580
+ if (!ref) refs.current.set(id, ref = slotRef(id));
3581
+ return ref;
3582
+ };
3583
+ const list = React4.useRef(null);
3584
+ const latest = React4.useRef(close);
3585
+ latest.current = close;
3586
+ React4.useEffect(() => {
3587
+ const element = list.current;
3588
+ if (!element) return;
3589
+ const onClick = (event) => {
3590
+ const target = event.target;
3591
+ const row = target.closest(".native-docx-ribbon-more-row");
3592
+ if (!row) return;
3593
+ const control = row.querySelector(".native-docx-ribbon-more-control");
3594
+ if (!control.contains(target)) {
3595
+ control.querySelector("button:not([disabled])")?.click();
3596
+ return;
3597
+ }
3598
+ const button = target.closest("button");
3599
+ if (button && !button.disabled && !control.querySelector(".native-docx-ribbon-popover")?.contains(button) && !button.hasAttribute("aria-expanded") && !button.hasAttribute("aria-haspopup"))
3600
+ latest.current();
3601
+ };
3602
+ element.addEventListener("click", onClick, true);
3603
+ return () => element.removeEventListener("click", onClick, true);
3604
+ }, []);
3605
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-ribbon-more-list", ref: list, children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-ribbon-more-row", "data-ribbon-more": entry.id, children: [
3606
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-ribbon-more-control", ref: refFor(entry.id) }),
3607
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-ribbon-more-label", children: entry.label })
3608
+ ] }, entry.id)) });
3609
+ }
3610
+ function RibbonItem({
3611
+ id,
3612
+ label,
3613
+ priority = 0,
3614
+ children
3615
+ }) {
3616
+ const context = React4.useContext(Overflow);
3617
+ const element = React4.useRef(null);
3618
+ const register = context?.register;
3619
+ React4.useLayoutEffect(() => {
3620
+ if (!register || !element.current) return;
3621
+ return register(id, { label, priority, element: element.current });
3622
+ }, [register, id, label, priority]);
3623
+ if (!context) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
3624
+ const collapsed = context.collapsed.has(id);
3625
+ const slot = context.slots[id];
3626
+ return /* @__PURE__ */ jsxRuntime.jsx(
3627
+ "span",
3628
+ {
3629
+ ref: element,
3630
+ className: "native-docx-ribbon-item",
3631
+ "data-ribbon-item": id,
3632
+ hidden: collapsed || void 0,
3633
+ children: collapsed ? slot ? reactDom.createPortal(children, slot) : null : children
3634
+ }
3635
+ );
3636
+ }
3637
+
2514
3638
  // src/docx/wordStyles.ts
2515
3639
  var QUICK_STYLES = ["Normal", "Title", "heading 1", "heading 2", "heading 3"];
2516
3640
  function findStyle(options, name) {
@@ -2574,14 +3698,14 @@ function Gallery({ close }) {
2574
3698
  const changed = new Set(
2575
3699
  house?.basedOnTemplate ? house.divergence?.styles.filter((s) => s.kind === "changed").map((s) => s.styleId) : []
2576
3700
  );
2577
- const [query, setQuery] = React3.useState("");
2578
- const quick = React3.useMemo(
3701
+ const [query, setQuery] = React4.useState("");
3702
+ const quick = React4.useMemo(
2579
3703
  () => QUICK_STYLES.map((name) => findStyle(options, name)).filter(
2580
3704
  (o) => !!o
2581
3705
  ),
2582
3706
  [options]
2583
3707
  );
2584
- const shown = React3.useMemo(() => {
3708
+ const shown = React4.useMemo(() => {
2585
3709
  const q = query.trim().toLowerCase();
2586
3710
  return q ? options.filter(
2587
3711
  (o) => o.name.toLowerCase().includes(q) || o.styleId.toLowerCase().includes(q)
@@ -2696,18 +3820,87 @@ function StyleGallery() {
2696
3820
  }
2697
3821
  );
2698
3822
  }
3823
+ var W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
3824
+ var DEFAULT_PARAGRAPH_FONT = {
3825
+ id: "DefaultParagraphFont",
3826
+ type: "character",
3827
+ 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>'
3828
+ };
3829
+ function stylesOf(kind) {
3830
+ const Kind = kind === "footnote" ? "Footnote" : "Endnote";
3831
+ const text = `${Kind}Text`;
3832
+ return [
3833
+ {
3834
+ id: text,
3835
+ type: "paragraph",
3836
+ 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>`
3837
+ },
3838
+ {
3839
+ id: `${text}Char`,
3840
+ type: "character",
3841
+ 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>`
3842
+ },
3843
+ {
3844
+ id: `${Kind}Reference`,
3845
+ type: "character",
3846
+ 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>`
3847
+ }
3848
+ ];
3849
+ }
3850
+ function noteTextStyle(styles, kind) {
3851
+ const paragraph = styles.filter((style) => style.type === "paragraph");
3852
+ const id = kind === "footnote" ? "FootnoteText" : "EndnoteText";
3853
+ return paragraph.find((style) => style.name.toLowerCase() === `${kind} text`)?.styleId ?? paragraph.find((style) => style.styleId === id)?.styleId;
3854
+ }
3855
+ function missingNoteStyles(styles, kind) {
3856
+ const has = (type, id) => styles.some((style) => style.type === type && style.styleId === id);
3857
+ const text = noteTextStyle(styles, kind);
3858
+ const missing = stylesOf(kind).filter(
3859
+ (style) => style.type === "paragraph" ? !text : !has("character", style.id)
3860
+ );
3861
+ if (!missing.length) return [];
3862
+ const base = has("character", DEFAULT_PARAGRAPH_FONT.id) ? [] : [DEFAULT_PARAGRAPH_FONT];
3863
+ return [...base, ...missing].map((style) => style.xml);
3864
+ }
3865
+ 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>';
3866
+ function stylesOnlyClipboardHtml(styles) {
3867
+ const fragment = fflate.zipSync({
3868
+ "[Content_Types].xml": fflate.strToU8(CONTENT_TYPES),
3869
+ "_rels/.rels": fflate.strToU8(
3870
+ '<?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>'
3871
+ ),
3872
+ "word/document.xml": fflate.strToU8(
3873
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
3874
+ <w:document xmlns:w="${W}"><w:body><w:p/></w:body></w:document>`
3875
+ ),
3876
+ "word/_rels/document.xml.rels": fflate.strToU8(
3877
+ '<?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>'
3878
+ ),
3879
+ "word/styles.xml": fflate.strToU8(
3880
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
3881
+ <w:styles xmlns:w="${W}">${styles.join("")}</w:styles>`
3882
+ )
3883
+ });
3884
+ return template.fragmentClipboardHtml(fragment, false);
3885
+ }
3886
+ function ensureNoteStyles(editor, kind, direct = (fn) => fn()) {
3887
+ if (!editor.can({ type: "insertNote", noteKind: kind }).ok) return void 0;
3888
+ const missing = missingNoteStyles(editor.getDocumentStyles(), kind);
3889
+ if (missing.length)
3890
+ direct(() => editor.exec({ type: "paste", text: "", html: stylesOnlyClipboardHtml(missing) }));
3891
+ return noteTextStyle(editor.getDocumentStyles(), kind);
3892
+ }
2699
3893
  function useInsertNote(kind) {
2700
3894
  const command = react.useEditorCommand(kind === "footnote" ? "insert.footnote" : "insert.endnote");
2701
- const { options } = react.useParagraphStyle();
2702
3895
  const editor = react.useDocxEditor();
2703
3896
  const insert = () => {
3897
+ const text = editor && ensureNoteStyles(editor, kind, (fn) => withDirectEditing(editor, fn));
2704
3898
  if (!command.execute()) return false;
2705
- const text = findStyle(options, `${kind} text`);
2706
- if (text && editor)
2707
- withDirectEditing(
2708
- editor,
2709
- () => editor.exec({ type: "setParagraphStyle", styleId: text.styleId })
2710
- );
3899
+ if (editor) {
3900
+ if (text)
3901
+ withDirectEditing(editor, () => editor.exec({ type: "setParagraphStyle", styleId: text }));
3902
+ editor.exec({ type: "insertText", text: " " });
3903
+ }
2711
3904
  return true;
2712
3905
  };
2713
3906
  return { insert, isEnabled: command.isEnabled, disabledReason: command.disabledReason };
@@ -2719,7 +3912,7 @@ function NoteAction({
2719
3912
  icon
2720
3913
  }) {
2721
3914
  const note = useInsertNote(kind);
2722
- return /* @__PURE__ */ jsxRuntime.jsx(
3915
+ return /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: `references-${kind}`, label, children: /* @__PURE__ */ jsxRuntime.jsx(
2723
3916
  react.DocxEditor.Toolbar.Action,
2724
3917
  {
2725
3918
  label: `${label} (${shortcut})`,
@@ -2729,7 +3922,7 @@ function NoteAction({
2729
3922
  onSelect: () => void note.insert(),
2730
3923
  className: `native-docx-insert-${kind}`
2731
3924
  }
2732
- );
3925
+ ) });
2733
3926
  }
2734
3927
  function NoteButtons() {
2735
3928
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -2759,9 +3952,9 @@ function WordShortcuts({ scope }) {
2759
3952
  const styles = react.useParagraphStyle();
2760
3953
  const editor = react.useDocxEditor();
2761
3954
  const levels = useHouseTemplate()?.levels;
2762
- const latest = React3.useRef({ footnote, endnote, styles, editor, levels });
3955
+ const latest = React4.useRef({ footnote, endnote, styles, editor, levels });
2763
3956
  latest.current = { footnote, endnote, styles, editor, levels };
2764
- React3.useEffect(() => {
3957
+ React4.useEffect(() => {
2765
3958
  const element = scope.current;
2766
3959
  if (!element) return;
2767
3960
  const onKeyDown = (event) => {
@@ -2799,6 +3992,65 @@ function WordShortcuts({ scope }) {
2799
3992
  }, [scope]);
2800
3993
  return null;
2801
3994
  }
3995
+ function CrossReferenceButton() {
3996
+ const references = useCrossReferences();
3997
+ if (!references) return null;
3998
+ return /* @__PURE__ */ jsxRuntime.jsx(
3999
+ "button",
4000
+ {
4001
+ type: "button",
4002
+ className: "native-docx-ribbon-trigger",
4003
+ "aria-label": references.labels.insert,
4004
+ title: references.labels.insert,
4005
+ "data-testid": "docx-insert-cross-reference",
4006
+ onMouseDown: (event) => event.preventDefault(),
4007
+ onClick: () => references.openDialog(),
4008
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { size: 16 })
4009
+ }
4010
+ );
4011
+ }
4012
+ function UpdateCrossReferencesButton() {
4013
+ const references = useCrossReferences();
4014
+ if (!references) return null;
4015
+ return /* @__PURE__ */ jsxRuntime.jsx(
4016
+ "button",
4017
+ {
4018
+ type: "button",
4019
+ className: "native-docx-ribbon-trigger",
4020
+ "aria-label": references.labels.update,
4021
+ title: references.labels.update,
4022
+ "data-testid": "docx-update-cross-references",
4023
+ onMouseDown: (event) => event.preventDefault(),
4024
+ onClick: () => references.update(),
4025
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCcw, { size: 16 })
4026
+ }
4027
+ );
4028
+ }
4029
+ function DocxContextMenuExtras() {
4030
+ const terms = useDefinedTerms();
4031
+ const references = useCrossReferences();
4032
+ if (!terms && !references) return null;
4033
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4034
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.ContextMenu.Separator, {}),
4035
+ terms && /* @__PURE__ */ jsxRuntime.jsx(
4036
+ react.DocxEditor.ContextMenu.Item,
4037
+ {
4038
+ label: "Insert defined term",
4039
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookA, { size: 14 }),
4040
+ shortcut: "@@",
4041
+ onSelect: () => terms.openPicker()
4042
+ }
4043
+ ),
4044
+ references && /* @__PURE__ */ jsxRuntime.jsx(
4045
+ react.DocxEditor.ContextMenu.Item,
4046
+ {
4047
+ label: references.labels.insert,
4048
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { size: 14 }),
4049
+ onSelect: () => references.openDialog()
4050
+ }
4051
+ )
4052
+ ] });
4053
+ }
2802
4054
 
2803
4055
  // src/docx/layout/presets.ts
2804
4056
  var TWIPS_PER_INCH = 1440;
@@ -3011,13 +4263,13 @@ function Breaks() {
3011
4263
  }
3012
4264
  function LayoutButtons() {
3013
4265
  const { pageSetup, apply } = react.usePageSetup();
3014
- const [dialog, setDialog] = React3.useState(false);
4266
+ const [dialog, setDialog] = React4.useState(false);
3015
4267
  const props = { setup: pageSetup, apply, openDialog: () => setDialog(true) };
3016
4268
  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(
4269
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "layout-margins", label: "Margins", children: /* @__PURE__ */ jsxRuntime.jsx(Margins, { ...props }) }),
4270
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "layout-orientation", label: "Orientation", children: /* @__PURE__ */ jsxRuntime.jsx(Orientation, { ...props }) }),
4271
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "layout-size", label: "Size", children: /* @__PURE__ */ jsxRuntime.jsx(Size, { ...props }) }),
4272
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "layout-columns", label: "Columns", children: /* @__PURE__ */ jsxRuntime.jsx(
3021
4273
  react.DocxEditor.Toolbar.Action,
3022
4274
  {
3023
4275
  label: "Columns",
@@ -3026,9 +4278,9 @@ function LayoutButtons() {
3026
4278
  disabledReason: COLUMNS_UNSUPPORTED,
3027
4279
  className: "native-docx-layout-columns"
3028
4280
  }
3029
- ),
3030
- /* @__PURE__ */ jsxRuntime.jsx(Breaks, {}),
3031
- /* @__PURE__ */ jsxRuntime.jsx(
4281
+ ) }),
4282
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "layout-breaks", label: "Breaks", children: /* @__PURE__ */ jsxRuntime.jsx(Breaks, {}) }),
4283
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "layout-page-setup", label: "Page Setup\u2026", children: /* @__PURE__ */ jsxRuntime.jsx(
3032
4284
  react.DocxEditor.Toolbar.Action,
3033
4285
  {
3034
4286
  label: "Page Setup\u2026",
@@ -3036,7 +4288,7 @@ function LayoutButtons() {
3036
4288
  onSelect: () => setDialog(true),
3037
4289
  className: "native-docx-layout-page-setup"
3038
4290
  }
3039
- ),
4291
+ ) }),
3040
4292
  /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.PageSetupDialog, { open: dialog, onClose: () => setDialog(false) })
3041
4293
  ] });
3042
4294
  }
@@ -3063,7 +4315,7 @@ function CommandGallery({
3063
4315
  rows
3064
4316
  }) {
3065
4317
  const bound = useRows(rows);
3066
- return /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsxRuntime.jsx(
4318
+ return /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: testId, label, children: /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsxRuntime.jsx(
3067
4319
  RibbonGallery,
3068
4320
  {
3069
4321
  label,
@@ -3077,7 +4329,7 @@ function CommandGallery({
3077
4329
  })),
3078
4330
  onPick: (id) => void bound.find((row) => row.id === id)?.state.execute()
3079
4331
  }
3080
- ) });
4332
+ ) }) });
3081
4333
  }
3082
4334
  function CommandAction({
3083
4335
  command,
@@ -3086,7 +4338,7 @@ function CommandAction({
3086
4338
  testId
3087
4339
  }) {
3088
4340
  const state = react.useEditorCommand(command);
3089
- return /* @__PURE__ */ jsxRuntime.jsx(
4341
+ return /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: `table-${testId}`, label, children: /* @__PURE__ */ jsxRuntime.jsx(
3090
4342
  react.DocxEditor.Toolbar.Action,
3091
4343
  {
3092
4344
  label,
@@ -3097,7 +4349,7 @@ function CommandAction({
3097
4349
  onSelect: () => void state.execute(),
3098
4350
  className: `native-docx-table-${testId}`
3099
4351
  }
3100
- );
4352
+ ) });
3101
4353
  }
3102
4354
  function TableButtons() {
3103
4355
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -3197,15 +4449,15 @@ function TableButtons() {
3197
4449
  ]
3198
4450
  }
3199
4451
  ),
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, {})
4452
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "table-border-target", label: "Borders", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderTarget, {}) }),
4453
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "table-border-style", label: "Border style", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderStyle, {}) }),
4454
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "table-border-width", label: "Border width", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderWidth, {}) }),
4455
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "table-border-color", label: "Border color", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableBorderColor, {}) }),
4456
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "table-cell-fill", label: "Shading", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableCellFill, {}) })
3205
4457
  ] });
3206
4458
  }
3207
4459
  var CAPTION_LABELS = ["Figure", "Table", "Equation"];
3208
- var CAPTION_STYLES = chunkAOFATOT3_cjs.stylesXml(
4460
+ var CAPTION_STYLES = chunk2A4MDHJR_cjs.stylesXml(
3209
4461
  "",
3210
4462
  '<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
4463
  );
@@ -3233,9 +4485,9 @@ function countSeqFields(root, label, throughId) {
3233
4485
  return count;
3234
4486
  }
3235
4487
  function captionParagraphXml(label, number, text) {
3236
- const run = (value) => `<w:r><w:t xml:space="preserve">${chunkAOFATOT3_cjs.esc(value)}</w:t></w:r>`;
4488
+ const run2 = (value) => `<w:r><w:t xml:space="preserve">${chunk2A4MDHJR_cjs.esc(value)}</w:t></w:r>`;
3237
4489
  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>`;
4490
+ return `<w:p><w:pPr><w:pStyle w:val="Caption"/></w:pPr>${run2(`${label} `)}<w:fldSimple w:instr=" SEQ ${chunk2A4MDHJR_cjs.esc(label)} \\* ARABIC "><w:r><w:t>${number}</w:t></w:r></w:fldSimple>${rest ? run2(rest) : ""}</w:p>`;
3239
4491
  }
3240
4492
  function base642(bytes) {
3241
4493
  let binary = "";
@@ -3244,8 +4496,8 @@ function base642(bytes) {
3244
4496
  return btoa(binary);
3245
4497
  }
3246
4498
  function captionFragmentHtml(label, number, text, revision) {
3247
- const untracked = chunkAOFATOT3_cjs.docxPackage({
3248
- document: chunkAOFATOT3_cjs.documentXml(captionParagraphXml(label, number, text)),
4499
+ const untracked = chunk2A4MDHJR_cjs.docxPackage({
4500
+ document: chunk2A4MDHJR_cjs.documentXml(captionParagraphXml(label, number, text)),
3249
4501
  styles: CAPTION_STYLES,
3250
4502
  title: "Caption"
3251
4503
  });
@@ -3264,7 +4516,7 @@ function TransformAction({
3264
4516
  icon
3265
4517
  }) {
3266
4518
  const state = react.useEditorCommand(TRANSFORMS[action]);
3267
- return /* @__PURE__ */ jsxRuntime.jsx(
4519
+ return /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: `picture-${action}`, label, children: /* @__PURE__ */ jsxRuntime.jsx(
3268
4520
  react.DocxEditor.Toolbar.Action,
3269
4521
  {
3270
4522
  label,
@@ -3274,7 +4526,7 @@ function TransformAction({
3274
4526
  onSelect: () => void state.execute(),
3275
4527
  className: `native-docx-picture-${action}`
3276
4528
  }
3277
- );
4529
+ ) });
3278
4530
  }
3279
4531
  function insertCaption(editor, label, text, track) {
3280
4532
  const surface = editor.surface;
@@ -3318,9 +4570,9 @@ function insertCaption(editor, label, text, track) {
3318
4570
  function CaptionButton({ defaultLabel = "Figure" }) {
3319
4571
  const editor = react.useDocxEditor();
3320
4572
  const track = useTrackedOrNoted();
3321
- const [label, setLabel] = React3.useState(defaultLabel);
3322
- const [text, setText] = React3.useState("");
3323
- const [error, setError] = React3.useState("");
4573
+ const [label, setLabel] = React4.useState(defaultLabel);
4574
+ const [text, setText] = React4.useState("");
4575
+ const [error, setError] = React4.useState("");
3324
4576
  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
4577
  "form",
3326
4578
  {
@@ -3372,9 +4624,9 @@ function CaptionButton({ defaultLabel = "Figure" }) {
3372
4624
  }
3373
4625
  function PictureButtons() {
3374
4626
  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, {}),
4627
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "picture-wrap", label: "Wrap text", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageWrap, {}) }),
4628
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "picture-properties", label: "Size and position", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageProperties, {}) }),
4629
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "picture-alt-text", label: "Alt text", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageAltText, {}) }),
3378
4630
  /* @__PURE__ */ jsxRuntime.jsx(TransformAction, { action: "rotateCW", label: "Rotate right 90\xB0", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCw, { size: 16 }) }),
3379
4631
  /* @__PURE__ */ jsxRuntime.jsx(TransformAction, { action: "rotateCCW", label: "Rotate left 90\xB0", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { size: 16 }) }),
3380
4632
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3386,7 +4638,7 @@ function PictureButtons() {
3386
4638
  }
3387
4639
  ),
3388
4640
  /* @__PURE__ */ jsxRuntime.jsx(TransformAction, { action: "flipV", label: "Flip vertical", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FlipVertical2, { size: 16 }) }),
3389
- /* @__PURE__ */ jsxRuntime.jsx(CaptionButton, {})
4641
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "picture-caption", label: "Insert caption", children: /* @__PURE__ */ jsxRuntime.jsx(CaptionButton, {}) })
3390
4642
  ] });
3391
4643
  }
3392
4644
  var LAYOUT_TAB = "Layout";
@@ -3439,9 +4691,9 @@ function tableCells(root, paragraphId) {
3439
4691
  }
3440
4692
  function TableTabKeys({ scope }) {
3441
4693
  const editor = react.useDocxEditor();
3442
- const latest = React3.useRef(editor);
4694
+ const latest = React4.useRef(editor);
3443
4695
  latest.current = editor;
3444
- React3.useEffect(() => {
4696
+ React4.useEffect(() => {
3445
4697
  const element = scope.current;
3446
4698
  if (!element) return;
3447
4699
  const onKeyDown = (event) => {
@@ -3587,7 +4839,7 @@ function covered(room, vector, receipt) {
3587
4839
  }
3588
4840
  return true;
3589
4841
  }
3590
- var EditorBoundary = class extends React3__default.default.Component {
4842
+ var EditorBoundary = class extends React4__default.default.Component {
3591
4843
  state = {};
3592
4844
  static getDerivedStateFromError(error) {
3593
4845
  return { error };
@@ -3600,8 +4852,8 @@ var EditorBoundary = class extends React3__default.default.Component {
3600
4852
  }
3601
4853
  };
3602
4854
  function DocxParticipants({ session }) {
3603
- const [people, setPeople] = React3.useState([]);
3604
- React3.useEffect(() => {
4855
+ const [people, setPeople] = React4.useState([]);
4856
+ React4.useEffect(() => {
3605
4857
  if (!session) return;
3606
4858
  setPeople(session.participants());
3607
4859
  return session.subscribeParticipants(setPeople);
@@ -3630,7 +4882,7 @@ function DocxRibbon({
3630
4882
  badge,
3631
4883
  imageGeneration
3632
4884
  }) {
3633
- const [selected, setTab] = React3.useState("Home");
4885
+ const [selected, setTab] = React4.useState("Home");
3634
4886
  const contextual = useContextualTabs(selected);
3635
4887
  useGenerateImageTarget();
3636
4888
  const tab = contextual.shown;
@@ -3649,46 +4901,53 @@ function DocxRibbon({
3649
4901
  /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Undo, {}),
3650
4902
  /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Redo, {}),
3651
4903
  /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Save, {}),
3652
- tab === "Home" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3653
- /* @__PURE__ */ jsxRuntime.jsx(StyleGallery, {}),
3654
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Bold, {}),
3655
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Italic, {}),
3656
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Underline, {}),
3657
- /* @__PURE__ */ jsxRuntime.jsxs(RibbonMenu, { label: "Font", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { size: 16 }), children: [
3658
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.FontFamily, {}),
3659
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.FontSize, {}),
3660
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.FontColor, {}),
3661
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Highlight, {})
4904
+ /* @__PURE__ */ jsxRuntime.jsxs(RibbonOverflow, { tab, children: [
4905
+ tab === "Home" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4906
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "home-style", label: "Styles", priority: 80, children: /* @__PURE__ */ jsxRuntime.jsx(StyleGallery, {}) }),
4907
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "home-bold", label: "Bold", priority: 100, children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Bold, {}) }),
4908
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "home-italic", label: "Italic", priority: 95, children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Italic, {}) }),
4909
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "home-underline", label: "Underline", priority: 90, children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Underline, {}) }),
4910
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "home-font", label: "Font", priority: 60, children: /* @__PURE__ */ jsxRuntime.jsxs(RibbonMenu, { label: "Font", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { size: 16 }), children: [
4911
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.FontFamily, {}),
4912
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.FontSize, {}),
4913
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.FontColor, {}),
4914
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Highlight, {})
4915
+ ] }) }),
4916
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "home-more-formatting", label: "More formatting", priority: 50, children: /* @__PURE__ */ jsxRuntime.jsxs(RibbonMenu, { label: "More formatting", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pilcrow, { size: 16 }), children: [
4917
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Alignment, {}),
4918
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.BulletList, {}),
4919
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.NumberedList, {}),
4920
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.LineSpacing, {}),
4921
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Indent, {}),
4922
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Outdent, {}),
4923
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Strike, {}),
4924
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ClearFormatting, {})
4925
+ ] }) })
4926
+ ] }),
4927
+ tab === "Insert" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4928
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-table", label: "Table", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableInsert, {}) }),
4929
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-picture", label: "Picture", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ImageInsert, {}) }),
4930
+ imageGeneration && /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-generate-image", label: "Generate image", children: /* @__PURE__ */ jsxRuntime.jsx(GenerateImageButton, { generation: imageGeneration }) }),
4931
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-page-break", label: "Page break", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Button, { slotId: "insert.pageBreak" }) }),
4932
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-link", label: "Link", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Link, {}) }),
4933
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-defined-term", label: "Defined term", children: /* @__PURE__ */ jsxRuntime.jsx(DefinedTermButtons, {}) }),
4934
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-quick-parts", label: "Quick Parts", children: /* @__PURE__ */ jsxRuntime.jsx(QuickParts, {}) }),
4935
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "insert-cross-reference", label: "Cross-reference", children: /* @__PURE__ */ jsxRuntime.jsx(CrossReferenceButton, {}) })
3662
4936
  ] }),
3663
- /* @__PURE__ */ jsxRuntime.jsxs(RibbonMenu, { label: "More formatting", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { size: 16 }), children: [
3664
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Alignment, {}),
3665
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.BulletList, {}),
3666
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.NumberedList, {}),
3667
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.LineSpacing, {}),
3668
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Indent, {}),
3669
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Outdent, {}),
3670
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Strike, {}),
3671
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.ClearFormatting, {})
4937
+ /* @__PURE__ */ jsxRuntime.jsx(LayoutTabContent, { tab }),
4938
+ tab === "Design" && /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "design-house-template", label: "House template", children: /* @__PURE__ */ jsxRuntime.jsx(HouseTemplatePanel, {}) }),
4939
+ tab === "References" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4940
+ /* @__PURE__ */ jsxRuntime.jsx(NoteButtons, {}),
4941
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "references-cross-reference", label: "Cross-reference", children: /* @__PURE__ */ jsxRuntime.jsx(CrossReferenceButton, {}) }),
4942
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "references-update-cross-references", label: "Update cross-references", children: /* @__PURE__ */ jsxRuntime.jsx(UpdateCrossReferencesButton, {}) })
4943
+ ] }),
4944
+ tab === "Review" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4945
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "review-editing-mode", label: "Editing mode", priority: 10, children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.EditingMode, {}) }),
4946
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "review-comments", label: "Comments", children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Comments, {}) }),
4947
+ /* @__PURE__ */ jsxRuntime.jsx(RibbonItem, { id: "review-options", label: "Review options", children: /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersRound, { size: 16 }), children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Reviewers, {}) }) })
3672
4948
  ] })
3673
4949
  ] }),
3674
- tab === "Insert" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3675
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableInsert, {}),
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" }),
3679
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Link, {}),
3680
- /* @__PURE__ */ jsxRuntime.jsx(DefinedTermButtons, {}),
3681
- /* @__PURE__ */ jsxRuntime.jsx(QuickParts, {})
3682
- ] }),
3683
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableCellFill, { hidden: true }),
3684
- /* @__PURE__ */ jsxRuntime.jsx(LayoutTabContent, { tab }),
3685
- tab === "Design" && /* @__PURE__ */ jsxRuntime.jsx(HouseTemplatePanel, {}),
3686
- tab === "References" && /* @__PURE__ */ jsxRuntime.jsx(NoteButtons, {}),
3687
- tab === "Review" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3688
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.EditingMode, {}),
3689
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Comments, {}),
3690
- /* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { size: 16 }), children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Reviewers, {}) })
3691
- ] })
4950
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.TableCellFill, { hidden: true })
3692
4951
  ] }),
3693
4952
  badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-ribbon-badge", "data-testid": "docx-ribbon-badge", children: badge })
3694
4953
  ] });
@@ -3704,18 +4963,18 @@ function NativeDocxEditor({
3704
4963
  stream,
3705
4964
  adapter
3706
4965
  }) {
3707
- const [ready, setReady] = React3.useState(), [error, setError] = React3.useState(""), [retry, setRetry] = React3.useState(0);
3708
- const [status, setStatus] = React3.useState("Connecting\u2026"), [dirty, setDirty] = React3.useState(false), [saving, setSaving] = React3.useState(false), [offline, setOffline] = React3.useState(false);
3709
- const revision = React3.useRef(0);
3710
- const stageRef = React3.useRef(null), fitCleanup = React3.useRef(void 0);
3711
- const ref = React3.useRef(null), dirtyRef = React3.useRef(false), draftTimer = React3.useRef(void 0);
4966
+ const [ready, setReady] = React4.useState(), [error, setError] = React4.useState(""), [retry, setRetry] = React4.useState(0);
4967
+ const [status, setStatus] = React4.useState("Connecting\u2026"), [dirty, setDirty] = React4.useState(false), [saving, setSaving] = React4.useState(false), [offline, setOffline] = React4.useState(false);
4968
+ const revision = React4.useRef(0);
4969
+ const stageRef = React4.useRef(null), fitCleanup = React4.useRef(void 0);
4970
+ const ref = React4.useRef(null), dirtyRef = React4.useRef(false), draftTimer = React4.useRef(void 0);
3712
4971
  const isDraft = draftContent !== void 0;
3713
- const streamRef = React3.useRef(stream);
4972
+ const streamRef = React4.useRef(stream);
3714
4973
  streamRef.current = stream;
3715
- const streamWriter = React3.useRef(null);
3716
- const streamFinished = React3.useRef(false);
3717
- const streamTimer = React3.useRef(void 0);
3718
- const [streamAttempt, setStreamAttempt] = React3.useState(0);
4974
+ const streamWriter = React4.useRef(null);
4975
+ const streamFinished = React4.useRef(false);
4976
+ const streamTimer = React4.useRef(void 0);
4977
+ const [streamAttempt, setStreamAttempt] = React4.useState(0);
3719
4978
  function updateStream() {
3720
4979
  const current = streamRef.current;
3721
4980
  if (!current || !streamWriter.current || streamFinished.current) return;
@@ -3731,7 +4990,7 @@ function NativeDocxEditor({
3731
4990
  );
3732
4991
  }
3733
4992
  }
3734
- React3.useEffect(() => {
4993
+ React4.useEffect(() => {
3735
4994
  if (!streamRef.current) return;
3736
4995
  if (!streamRef.current.busy) {
3737
4996
  clearTimeout(streamTimer.current);
@@ -3744,8 +5003,8 @@ function NativeDocxEditor({
3744
5003
  }, 120);
3745
5004
  }
3746
5005
  }, [stream?.content, stream?.busy, stream?.error, streamAttempt]);
3747
- React3.useEffect(() => () => clearTimeout(streamTimer.current), []);
3748
- React3.useEffect(() => {
5006
+ React4.useEffect(() => () => clearTimeout(streamTimer.current), []);
5007
+ React4.useEffect(() => {
3749
5008
  let cancelled = false;
3750
5009
  let room;
3751
5010
  const cleanups = [];
@@ -3873,7 +5132,7 @@ function NativeDocxEditor({
3873
5132
  room?.destroy();
3874
5133
  };
3875
5134
  }, [documentId, isDraft, snapshot, retry]);
3876
- React3.useEffect(() => {
5135
+ React4.useEffect(() => {
3877
5136
  adapter.onDirtyChange?.(dirty);
3878
5137
  const beforeUnload = (e) => {
3879
5138
  if (dirtyRef.current) e.preventDefault();
@@ -3885,6 +5144,7 @@ function NativeDocxEditor({
3885
5144
  };
3886
5145
  }, [dirty]);
3887
5146
  async function exportDocument() {
5147
+ runBeforeSave(ref.current);
3888
5148
  const data = await ref.current?.save();
3889
5149
  if (!data) return;
3890
5150
  const url = URL.createObjectURL(
@@ -3898,7 +5158,7 @@ function NativeDocxEditor({
3898
5158
  a.click();
3899
5159
  setTimeout(() => URL.revokeObjectURL(url), 5e3);
3900
5160
  }
3901
- React3.useLayoutEffect(() => {
5161
+ React4.useLayoutEffect(() => {
3902
5162
  const editor = ref.current;
3903
5163
  return () => {
3904
5164
  if (isDraft && editor && dirtyRef.current)
@@ -3911,6 +5171,7 @@ function NativeDocxEditor({
3911
5171
  async function saveVersion() {
3912
5172
  if (!ready || saving || stream) return;
3913
5173
  setSaving(true);
5174
+ runBeforeSave(ref.current);
3914
5175
  const atRevision = revision.current;
3915
5176
  try {
3916
5177
  const result = isDraft ? await (async () => {
@@ -4034,7 +5295,7 @@ function NativeDocxEditor({
4034
5295
  load: adapter.definitions,
4035
5296
  editable: !stream && !snapshot && ready.canEdit,
4036
5297
  notify: adapter.notify,
4037
- children: /* @__PURE__ */ jsxRuntime.jsxs(
5298
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4038
5299
  HouseTemplateProvider,
4039
5300
  {
4040
5301
  enabled: !stream,
@@ -4042,67 +5303,76 @@ function NativeDocxEditor({
4042
5303
  documentId: isDraft || snapshot ? void 0 : documentId,
4043
5304
  editable: !stream && !snapshot && ready.canEdit,
4044
5305
  notify: adapter.notify,
4045
- children: [
4046
- /* @__PURE__ */ jsxRuntime.jsx(
4047
- react.DocxEditor.RevisionMarkup,
4048
- {
4049
- insertions: { mark: "underline", color: "blue" },
4050
- deletions: { mark: "strikethrough", color: "red" },
4051
- movedFrom: { mark: "doubleStrikethrough", color: "green" },
4052
- movedTo: { mark: "doubleUnderline", color: "green" },
4053
- trackMoves: true
4054
- }
4055
- ),
4056
- !stream && /* @__PURE__ */ jsxRuntime.jsx(
4057
- DocxRibbon,
4058
- {
4059
- onSave: () => void saveVersion(),
4060
- imageGeneration: adapter.imageGeneration && {
4061
- notify: adapter.notify,
4062
- ...adapter.imageGeneration
4063
- },
4064
- badge: (
4065
- // Says the document is shared live, in place of a title row above the ribbon.
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
5306
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
5307
+ CrossReferencesProvider,
5308
+ {
5309
+ editable: !stream && !snapshot && ready.canEdit,
5310
+ references: adapter.references,
5311
+ documentId,
5312
+ notify: adapter.notify,
5313
+ children: [
5314
+ /* @__PURE__ */ jsxRuntime.jsx(
5315
+ react.DocxEditor.RevisionMarkup,
5316
+ {
5317
+ insertions: { mark: "underline", color: "blue" },
5318
+ deletions: { mark: "strikethrough", color: "red" },
5319
+ movedFrom: { mark: "doubleStrikethrough", color: "green" },
5320
+ movedTo: { mark: "doubleUnderline", color: "green" },
5321
+ trackMoves: true
5322
+ }
5323
+ ),
5324
+ !stream && /* @__PURE__ */ jsxRuntime.jsx(
5325
+ DocxRibbon,
5326
+ {
5327
+ onSave: () => void saveVersion(),
5328
+ imageGeneration: adapter.imageGeneration && {
5329
+ notify: adapter.notify,
5330
+ ...adapter.imageGeneration
5331
+ },
5332
+ badge: (
5333
+ // Says the document is shared live, in place of a title row above the ribbon.
5334
+ 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
5335
+ )
5336
+ }
5337
+ ),
5338
+ !stream && /* @__PURE__ */ jsxRuntime.jsx(WordShortcuts, { scope: stageRef }),
5339
+ !stream && /* @__PURE__ */ jsxRuntime.jsx(TableTabKeys, { scope: stageRef }),
5340
+ /* @__PURE__ */ jsxRuntime.jsxs(
5341
+ "div",
5342
+ {
5343
+ className: "native-docx-stage",
5344
+ ref: stageRef,
5345
+ onMouseDownCapture: (event) => {
5346
+ if (event.button === 2 && ref.current?.getSelectionPlacement())
5347
+ event.preventDefault();
5348
+ },
5349
+ children: [
5350
+ /* @__PURE__ */ jsxRuntime.jsxs(react.DocxEditor.Viewport, { className: "native-docx-viewport", children: [
5351
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Content, {}),
5352
+ /* @__PURE__ */ jsxRuntime.jsx(
5353
+ DocxMentions,
5354
+ {
5355
+ initialCommentId,
5356
+ mentions: adapter.mentions,
5357
+ notify: adapter.notify,
5358
+ getAgentStatus: adapter.getAgentStatus,
5359
+ requestAgent: adapter.requestAgent ? (request) => adapter.requestAgent(documentId, request) : void 0,
5360
+ children: /* @__PURE__ */ jsxRuntime.jsx(DocxEditorReview, { children: () => /* @__PURE__ */ jsxRuntime.jsx(DocxEditorReview.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(DocxCommentActivity, {}) }) })
5361
+ }
5362
+ ),
5363
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.HeaderFooterChrome, {}),
5364
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.NotesChrome, {}),
5365
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Equation, {}),
5366
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.HyperLink, {}),
5367
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.ContextMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(DocxContextMenuExtras, {}) })
5368
+ ] }),
5369
+ /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.PageNumber, {})
5370
+ ]
5371
+ }
4067
5372
  )
4068
- }
4069
- ),
4070
- !stream && /* @__PURE__ */ jsxRuntime.jsx(WordShortcuts, { scope: stageRef }),
4071
- !stream && /* @__PURE__ */ jsxRuntime.jsx(TableTabKeys, { scope: stageRef }),
4072
- /* @__PURE__ */ jsxRuntime.jsxs(
4073
- "div",
4074
- {
4075
- className: "native-docx-stage",
4076
- ref: stageRef,
4077
- onMouseDownCapture: (event) => {
4078
- if (event.button === 2 && ref.current?.getSelectionPlacement())
4079
- event.preventDefault();
4080
- },
4081
- children: [
4082
- /* @__PURE__ */ jsxRuntime.jsxs(react.DocxEditor.Viewport, { className: "native-docx-viewport", children: [
4083
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Content, {}),
4084
- /* @__PURE__ */ jsxRuntime.jsx(
4085
- DocxMentions,
4086
- {
4087
- initialCommentId,
4088
- mentions: adapter.mentions,
4089
- notify: adapter.notify,
4090
- getAgentStatus: adapter.getAgentStatus,
4091
- requestAgent: adapter.requestAgent ? (request) => adapter.requestAgent(documentId, request) : void 0,
4092
- children: /* @__PURE__ */ jsxRuntime.jsx(DocxEditorReview, { children: () => /* @__PURE__ */ jsxRuntime.jsx(DocxEditorReview.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(DocxCommentActivity, {}) }) })
4093
- }
4094
- ),
4095
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.HeaderFooterChrome, {}),
4096
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.NotesChrome, {}),
4097
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Equation, {}),
4098
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.HyperLink, {}),
4099
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.ContextMenu, {})
4100
- ] }),
4101
- /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.PageNumber, {})
4102
- ]
4103
- }
4104
- )
4105
- ]
5373
+ ]
5374
+ }
5375
+ )
4106
5376
  }
4107
5377
  )
4108
5378
  }
@@ -4202,6 +5472,9 @@ async function loadFonts(baseUrl) {
4202
5472
  }
4203
5473
 
4204
5474
  exports.BUILTIN_TEMPLATE_NAME = BUILTIN_TEMPLATE_NAME;
5475
+ exports.CrossReferenceDialog = CrossReferenceDialog;
5476
+ exports.CrossReferencesProvider = CrossReferencesProvider;
5477
+ exports.DEFAULT_CROSS_REFERENCES_LABELS = DEFAULT_CROSS_REFERENCES_LABELS;
4205
5478
  exports.DEFAULT_DEFINED_TERMS_LABELS = DEFAULT_DEFINED_TERMS_LABELS;
4206
5479
  exports.DEFINED_TERM_TRIGGER = DEFINED_TERM_TRIGGER;
4207
5480
  exports.DefinedTermsProvider = DefinedTermsProvider;
@@ -4213,24 +5486,33 @@ exports.DocxParticipants = DocxParticipants;
4213
5486
  exports.DocxRibbon = DocxRibbon;
4214
5487
  exports.GenerateImageButton = GenerateImageButton;
4215
5488
  exports.HouseTemplateProvider = HouseTemplateProvider;
5489
+ exports.LinkHoverCard = LinkHoverCard;
4216
5490
  exports.NativeDocxEditor = NativeDocxEditor;
4217
5491
  exports.builtinHouseTemplate = builtinHouseTemplate;
4218
5492
  exports.contentPath = contentPath;
4219
5493
  exports.editorPort = editorPort;
4220
5494
  exports.findDefinitionsSection = findDefinitionsSection;
5495
+ exports.insertCrossReference = insertCrossReference;
4221
5496
  exports.insertDefinedTerm = insertDefinedTerm;
5497
+ exports.insertDocumentReference = insertDocumentReference;
5498
+ exports.listTargets = listTargets;
4222
5499
  exports.loadDocxFonts = loadDocxFonts;
4223
5500
  exports.normalizeDocxExport = normalizeDocxExport;
5501
+ exports.paragraphNumber = paragraphNumber;
5502
+ exports.referenceText = referenceText;
5503
+ exports.referencesPort = referencesPort;
4224
5504
  exports.resolveHouseTemplate = resolveHouseTemplate;
4225
5505
  exports.reviewModule = reviewModule;
5506
+ exports.shortTitle = shortTitle;
4226
5507
  exports.structuralPort = structuralPort;
4227
5508
  exports.templateFileName = templateFileName;
4228
5509
  exports.trackedOrNoted = trackedOrNoted;
5510
+ exports.useCrossReferences = useCrossReferences;
4229
5511
  exports.useDefinedTerms = useDefinedTerms;
4230
5512
  exports.useHouseTemplate = useHouseTemplate;
4231
5513
  exports.useReview = useReview;
4232
5514
  exports.useReviewItem = useReviewItem;
4233
5515
  exports.useTrackedOrNoted = useTrackedOrNoted;
4234
5516
  exports.withDirectEditing = withDirectEditing;
4235
- //# sourceMappingURL=chunk-FAGQTB3D.cjs.map
4236
- //# sourceMappingURL=chunk-FAGQTB3D.cjs.map
5517
+ //# sourceMappingURL=chunk-ZWWN4CUL.cjs.map
5518
+ //# sourceMappingURL=chunk-ZWWN4CUL.cjs.map