@stll/folio-react 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,11 +7,12 @@ import { AlertCircleIcon, AlertTriangleIcon, AlignCenterIcon, AlignJustifyIcon,
7
7
  import { closeHistory, redo, undo } from "prosemirror-history";
8
8
  import { IntlProvider, useTranslations } from "use-intl";
9
9
  import { FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, createFolioAIEditSnapshot, getCommentAnchorsFromDoc, getFolioDocumentOperationIssues, getTrackedChangesFromDoc } from "@stll/folio-core/ai-edits";
10
+ import { resolveActiveEditorStory } from "@stll/folio-core/controller/activeEditorStory";
10
11
  import { normalizeBaseDirection } from "@stll/folio-core/docx/normalizeBaseDirection";
11
12
  import { getCachedNumberingMap } from "@stll/folio-core/docx/numberingParser";
12
13
  import { computeScrollPageInfo, updateScrollPageTotal } from "@stll/folio-core/paged-layout/scrollPageInfo";
13
14
  import { TextSelection, addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, captureFormatMarks, clearFormatting, clearTextColor, createStyleResolver, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, extractSelectionState, getSelectedText, getTableContext, increaseIndent, increaseListLevel, mergeCells, removeTabStop, removeTableBorders, schema, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableProperties, setTextColor, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline } from "@stll/folio-core/prosemirror";
14
- import { acceptAIEditRevision, acceptChange, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, rejectAIEditRevision, rejectChange } from "@stll/folio-core/prosemirror/commands/comments";
15
+ import { acceptAIEditRevision, acceptChange, acceptSuggestion, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectChange, rejectSuggestion } from "@stll/folio-core/prosemirror/commands/comments";
15
16
  import { blockSdtAttrsToSdtProperties, findBlockSdtMatch, findBlockSdtMatches, removeContentControlTr, setContentControlContentTr, setContentControlValueTr } from "@stll/folio-core/prosemirror/commands/contentControls";
16
17
  import { setContentControlContentBlocksTr } from "@stll/folio-core/prosemirror/commands/contentControlsBlockFill";
17
18
  import { CLIPBOARD_READ_ERROR_EVENT, buildPlainTextSlice } from "@stll/folio-core/prosemirror/commands/pastePlainText";
@@ -24,7 +25,7 @@ import { createAICitationDecorationsPlugin } from "@stll/folio-core/prosemirror/
24
25
  import { AI_SUGGESTION_SEVERITY_CLASS, aiSuggestionDecorationsKey, createAISuggestionDecorationsPlugin } from "@stll/folio-core/prosemirror/plugins/aiSuggestionDecorations";
25
26
  import { anonymizationDecorationsKey, createAnonymizationDecorationsPlugin, slugAnonymizationLabel } from "@stll/folio-core/prosemirror/plugins/anonymizationDecorations";
26
27
  import { autocompleteSuggestionKey, autocompleteSuggestionPlugin } from "@stll/folio-core/prosemirror/plugins/autocompleteSuggestion";
27
- import { createSuggestionModePlugin, setSuggestionMode } from "@stll/folio-core/prosemirror/plugins/suggestionMode";
28
+ import { createSuggestionModePlugin, setSuggestionMode, suggestionModeKey } from "@stll/folio-core/prosemirror/plugins/suggestionMode";
28
29
  import { createTemplateDirectivesPlugin, templateDirectivesKey } from "@stll/folio-core/prosemirror/plugins/templateDirectives";
29
30
  import { createTemplatePreviewValuesPlugin, templatePreviewValuesKey } from "@stll/folio-core/prosemirror/plugins/templatePreviewValues";
30
31
  import { getTemplateSlashMenu, templateSlashMenuPlugin } from "@stll/folio-core/prosemirror/plugins/templateSlashMenu";
@@ -40,6 +41,7 @@ import { NodeSelection, Selection, TextSelection as TextSelection$1 } from "pros
40
41
  import { CellSelection } from "prosemirror-tables";
41
42
  import { createHeaderFooterEditorManager } from "@stll/folio-core/controller/headerFooterEditorManager";
42
43
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
44
+ import { createNoteEditorManager } from "@stll/folio-core/controller/noteEditorManager";
43
45
  import { createFolioEditor } from "@stll/folio-core/controller/folioEditor";
44
46
  import { createFolioEditorEmitter } from "@stll/folio-core/controller/folioEditorEvents";
45
47
  import { createLatestRequestGate } from "@stll/folio-core/controller/latestRequestGate";
@@ -53,9 +55,11 @@ import { templatePreviewDirtyRange } from "@stll/folio-core/layout-bridge/conver
53
55
  import { clickToPositionDom } from "@stll/folio-core/layout-bridge/dom/clickToPositionDom";
54
56
  import { findBodyEmptyRuns, findBodyPmAnchor, findBodyPmAnchors, findBodyPmSpans } from "@stll/folio-core/layout-bridge/dom/findBodyPmSpans";
55
57
  import { clickToPositionInHfSlot, findHfCaretSpan, findHfPmSpans, findHfSlotForTarget, findHfSlotKindForTarget } from "@stll/folio-core/layout-bridge/dom/findHfPmSpans";
58
+ import { findNoteStoryForTarget } from "@stll/folio-core/layout-bridge/dom/noteStoryDom";
56
59
  import { clickToPosition } from "@stll/folio-core/layout-bridge/engine/clickToPosition";
57
60
  import { getPageTop, hitTestFragment, hitTestTableCell } from "@stll/folio-core/layout-bridge/engine/hitTest";
58
61
  import { clearAllCaches, resetCanvasContext } from "@stll/folio-core/layout-bridge/engine/measuring";
62
+ import { setEmbeddedFontFamilyMap } from "@stll/folio-core/utils/fontResolver";
59
63
  import { resolveSectionHeaderFooterRefs } from "@stll/folio-core/layout-engine";
60
64
  import { recordLayoutPhase } from "@stll/folio-core/layout-engine/layoutInstrumentation";
61
65
  import { LayoutPainter } from "@stll/folio-core/layout-painter";
@@ -72,13 +76,14 @@ import { tableInsertButtonOffset } from "@stll/folio-core/paged-layout/tableInse
72
76
  import { getTransactionDirtyRange } from "@stll/folio-core/paged-layout/transactionDirtyRange";
73
77
  import { findStartPosForParaId } from "@stll/folio-core/prosemirror/utils/findParagraphByParaId";
74
78
  import { expectImageAttrs, expectTableAttrs, expectTableCellAttrs, mergeImageAttrs, mergeTableAttrs, mergeTableCellAttrs, mergeTableRowAttrs } from "@stll/folio-core/prosemirror/attrs";
75
- import { extractEmbeddedFonts } from "@stll/folio-core/fonts/embeddedFonts";
79
+ import { buildEmbeddedFontFamilyMap, extractEmbeddedFonts } from "@stll/folio-core/fonts/embeddedFonts";
76
80
  import { panic } from "better-result";
77
81
  import { collectRemoteSelections, createHiddenEditorManager, createHiddenEditorState } from "@stll/folio-core/controller/hiddenEditorManager";
78
82
  import { loadCollaborationModules } from "@stll/folio-core/controller/collaborationModules";
79
- import { clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange } from "@stll/folio-core/ai-edits/blockRange";
83
+ import { clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange } from "@stll/folio-core/ai-edits/blockRange";
84
+ import { getFolioParaIdFromBlockId } from "@stll/folio-core/types/block-id";
80
85
  import { getPageTextFromLayout } from "@stll/folio-core/paged-layout/pageText";
81
- import { CONTENT_CONTROL_WIDGET_EVENT_NAME, dispatchDatePick, dispatchDropdownPick } from "@stll/folio-core/prosemirror/plugins/contentControlWidgets";
86
+ import { ContentControlWidgetController } from "@stll/folio-core/controller/contentControlWidgetController";
82
87
  import { createDefaultFindOptions, findInDocument } from "@stll/folio-core/utils/findReplace";
83
88
  import { ErrorManager } from "@stll/folio-core/managers/ErrorManager";
84
89
  import { ContextMenuManager } from "@stll/folio-core/managers/ContextMenuManager";
@@ -93,6 +98,7 @@ import { applyImagePosition, applyImageProperties, applyImageTransform, applyIma
93
98
  import { classifyEditorKeydown, deleteSelectedTable, isFocusInInputLike, isMacPlatform } from "@stll/folio-core/managers/editorShortcuts";
94
99
  import { getScrollTopForZoomAnchor, getViewportCenterZoomAnchorForZoomChange } from "@stll/folio-core/paged-layout/zoomScrollAnchor";
95
100
  import { ZOOM_MAX, ZOOM_MIN, ZOOM_STEP } from "@stll/folio-core/utils/zoom";
101
+ import { isValidHexId } from "@stll/folio-core/utils/hexId";
96
102
  import { createRoot } from "react-dom/client";
97
103
  //#region src/hooks/useHistory.ts
98
104
  /**
@@ -194,7 +200,7 @@ function useDocumentHistory(document, t0) {
194
200
  $[1] = t1;
195
201
  } else t1 = $[1];
196
202
  const options = t1;
197
- const isEqual = _temp$10;
203
+ const isEqual = _temp$11;
198
204
  let t2;
199
205
  if ($[2] !== options) {
200
206
  t2 = {
@@ -206,7 +212,7 @@ function useDocumentHistory(document, t0) {
206
212
  } else t2 = $[3];
207
213
  return useHistory(document, t2);
208
214
  }
209
- function _temp$10(a, b) {
215
+ function _temp$11(a, b) {
210
216
  if (a === b) return true;
211
217
  const aPackage = a?.package;
212
218
  const bPackage = b?.package;
@@ -361,6 +367,292 @@ const HiddenHeaderFooterPMs = memo(forwardRef(function HiddenHeaderFooterPMs({ d
361
367
  }));
362
368
  HiddenHeaderFooterPMs.displayName = "HiddenHeaderFooterPMs";
363
369
  //#endregion
370
+ //#region src/components/NoteStoryEditor.tsx
371
+ /** Thin React surface over core's persistent note-story editor manager. */
372
+ const panelStyle = {
373
+ position: "absolute",
374
+ right: 24,
375
+ bottom: 24,
376
+ width: "min(560px, calc(100% - 48px))",
377
+ maxHeight: "45%",
378
+ overflow: "auto",
379
+ zIndex: 30,
380
+ background: "var(--doc-canvas, #fff)",
381
+ color: "var(--doc-canvas-text, #000)",
382
+ border: "1px solid var(--doc-border, rgba(0, 0, 0, 0.18))",
383
+ borderRadius: 6,
384
+ boxShadow: "0 8px 28px rgba(0, 0, 0, 0.18)"
385
+ };
386
+ const headerStyle = {
387
+ position: "sticky",
388
+ top: 0,
389
+ zIndex: 1,
390
+ display: "flex",
391
+ alignItems: "center",
392
+ justifyContent: "space-between",
393
+ padding: "8px 12px",
394
+ background: "var(--doc-canvas, #fff)",
395
+ borderBottom: "1px solid var(--doc-border, rgba(0, 0, 0, 0.12))",
396
+ fontSize: 12,
397
+ fontWeight: 600
398
+ };
399
+ const hostStyle = {
400
+ padding: "12px 16px",
401
+ minHeight: 72
402
+ };
403
+ const EMPTY_PLUGINS$1 = [];
404
+ const NoteStoryEditor = forwardRef(function NoteStoryEditor(t0, ref) {
405
+ const $ = c(51);
406
+ const { document, onActiveChange, onDocumentChange, onStoryChange, plugins, styles, suggestionAuthor, suggestionModeActive, theme } = t0;
407
+ const t = useTranslations("folio");
408
+ const resolvedPlugins = plugins ?? EMPTY_PLUGINS$1;
409
+ const isSuggestionModeActive = suggestionModeActive ?? false;
410
+ const hostRef = useRef(null);
411
+ const documentRef = useRef(document);
412
+ const stylesRef = useRef(styles);
413
+ const themeRef = useRef(theme);
414
+ const pluginsRef = useRef(resolvedPlugins);
415
+ const onDocumentChangeRef = useRef(onDocumentChange);
416
+ const onActiveChangeRef = useRef(onActiveChange);
417
+ const onStoryChangeRef = useRef(onStoryChange);
418
+ const [active, setActive] = useState(null);
419
+ const managerRef = useRef(null);
420
+ const footnotes = document?.package.footnotes;
421
+ const endnotes = document?.package.endnotes;
422
+ let t1;
423
+ if ($[0] !== active || $[1] !== document || $[2] !== onActiveChange || $[3] !== onDocumentChange || $[4] !== onStoryChange || $[5] !== resolvedPlugins || $[6] !== styles || $[7] !== theme) {
424
+ t1 = () => {
425
+ documentRef.current = document;
426
+ stylesRef.current = styles;
427
+ themeRef.current = theme;
428
+ pluginsRef.current = resolvedPlugins;
429
+ onDocumentChangeRef.current = onDocumentChange;
430
+ onActiveChangeRef.current = onActiveChange;
431
+ onStoryChangeRef.current = onStoryChange;
432
+ if (managerRef.current === null) managerRef.current = createNoteEditorManager({
433
+ getDocument: () => documentRef.current,
434
+ getHost: () => hostRef.current,
435
+ getPlugins: () => pluginsRef.current,
436
+ getStyles: () => stylesRef.current,
437
+ getTheme: () => themeRef.current,
438
+ onTransaction: (t2) => {
439
+ const { docChanged, selectionChanged, view } = t2;
440
+ if (docChanged) {
441
+ const current = documentRef.current;
442
+ if (current) onDocumentChangeRef.current(managerRef.current?.snapshotDocument(current) ?? current);
443
+ }
444
+ onStoryChangeRef.current(view, docChanged, selectionChanged);
445
+ }
446
+ });
447
+ const manager = managerRef.current;
448
+ manager.sync();
449
+ if (active && !manager?.getActive()) {
450
+ setActive(null);
451
+ onActiveChangeRef.current(null);
452
+ }
453
+ };
454
+ $[0] = active;
455
+ $[1] = document;
456
+ $[2] = onActiveChange;
457
+ $[3] = onDocumentChange;
458
+ $[4] = onStoryChange;
459
+ $[5] = resolvedPlugins;
460
+ $[6] = styles;
461
+ $[7] = theme;
462
+ $[8] = t1;
463
+ } else t1 = $[8];
464
+ let t2;
465
+ if ($[9] !== active || $[10] !== document || $[11] !== endnotes || $[12] !== footnotes || $[13] !== onActiveChange || $[14] !== onDocumentChange || $[15] !== onStoryChange || $[16] !== resolvedPlugins || $[17] !== styles || $[18] !== theme) {
466
+ t2 = [
467
+ active,
468
+ document,
469
+ endnotes,
470
+ footnotes,
471
+ onActiveChange,
472
+ onDocumentChange,
473
+ onStoryChange,
474
+ resolvedPlugins,
475
+ styles,
476
+ theme
477
+ ];
478
+ $[9] = active;
479
+ $[10] = document;
480
+ $[11] = endnotes;
481
+ $[12] = footnotes;
482
+ $[13] = onActiveChange;
483
+ $[14] = onDocumentChange;
484
+ $[15] = onStoryChange;
485
+ $[16] = resolvedPlugins;
486
+ $[17] = styles;
487
+ $[18] = theme;
488
+ $[19] = t2;
489
+ } else t2 = $[19];
490
+ useEffect(t1, t2);
491
+ let t3;
492
+ let t4;
493
+ if ($[20] !== isSuggestionModeActive || $[21] !== suggestionAuthor) {
494
+ t3 = () => {
495
+ const manager_0 = managerRef.current;
496
+ if (!manager_0) return;
497
+ for (const story of manager_0.listStories()) {
498
+ const view_0 = manager_0.getView(story);
499
+ if (view_0) setSuggestionMode(isSuggestionModeActive, view_0.state, view_0.dispatch, suggestionAuthor);
500
+ }
501
+ };
502
+ t4 = [isSuggestionModeActive, suggestionAuthor];
503
+ $[20] = isSuggestionModeActive;
504
+ $[21] = suggestionAuthor;
505
+ $[22] = t3;
506
+ $[23] = t4;
507
+ } else {
508
+ t3 = $[22];
509
+ t4 = $[23];
510
+ }
511
+ useEffect(t3, t4);
512
+ let t5;
513
+ let t6;
514
+ if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
515
+ t5 = () => () => {
516
+ managerRef.current?.destroy();
517
+ };
518
+ t6 = [];
519
+ $[24] = t5;
520
+ $[25] = t6;
521
+ } else {
522
+ t5 = $[24];
523
+ t6 = $[25];
524
+ }
525
+ useEffect(t5, t6);
526
+ let t7;
527
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
528
+ t7 = () => {
529
+ managerRef.current?.activate(null);
530
+ setActive(null);
531
+ onActiveChangeRef.current(null);
532
+ };
533
+ $[26] = t7;
534
+ } else t7 = $[26];
535
+ const closeEditor = t7;
536
+ let t8;
537
+ if ($[27] !== isSuggestionModeActive || $[28] !== suggestionAuthor) {
538
+ t8 = () => ({
539
+ close: closeEditor,
540
+ getActiveView: () => {
541
+ const story_0 = managerRef.current?.getActive();
542
+ return story_0 ? managerRef.current?.getView(story_0) ?? null : null;
543
+ },
544
+ open: (story_1) => {
545
+ const view_1 = managerRef.current?.activate(story_1);
546
+ if (!view_1) return;
547
+ setSuggestionMode(isSuggestionModeActive, view_1.state, view_1.dispatch, suggestionAuthor);
548
+ setActive(story_1);
549
+ onActiveChangeRef.current(story_1);
550
+ requestAnimationFrame(() => view_1.focus());
551
+ },
552
+ snapshotDocument: (current_0) => managerRef.current?.snapshotDocument(current_0) ?? current_0
553
+ });
554
+ $[27] = isSuggestionModeActive;
555
+ $[28] = suggestionAuthor;
556
+ $[29] = t8;
557
+ } else t8 = $[29];
558
+ useImperativeHandle(ref, t8);
559
+ let t9;
560
+ if ($[30] !== active || $[31] !== t) {
561
+ t9 = active ? t(active.kind === "footnote" ? "dialogs.footnoteProperties.footnotes" : "dialogs.footnoteProperties.endnotes") : "";
562
+ $[30] = active;
563
+ $[31] = t;
564
+ $[32] = t9;
565
+ } else t9 = $[32];
566
+ const title = t9;
567
+ const t10 = active ? "block" : "none";
568
+ let t11;
569
+ if ($[33] !== t10) {
570
+ t11 = {
571
+ ...panelStyle,
572
+ display: t10
573
+ };
574
+ $[33] = t10;
575
+ $[34] = t11;
576
+ } else t11 = $[34];
577
+ let t12;
578
+ if ($[35] === Symbol.for("react.memo_cache_sentinel")) {
579
+ t12 = (event) => {
580
+ if (event.key !== "Escape") return;
581
+ event.preventDefault();
582
+ event.stopPropagation();
583
+ closeEditor();
584
+ };
585
+ $[35] = t12;
586
+ } else t12 = $[35];
587
+ let t13;
588
+ if ($[36] !== title) {
589
+ t13 = /* @__PURE__ */ jsx("span", { children: title });
590
+ $[36] = title;
591
+ $[37] = t13;
592
+ } else t13 = $[37];
593
+ let t14;
594
+ if ($[38] !== t) {
595
+ t14 = t("common.closeDialog");
596
+ $[38] = t;
597
+ $[39] = t14;
598
+ } else t14 = $[39];
599
+ let t15;
600
+ if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
601
+ t15 = {
602
+ border: 0,
603
+ background: "transparent",
604
+ color: "inherit",
605
+ cursor: "pointer"
606
+ };
607
+ $[40] = t15;
608
+ } else t15 = $[40];
609
+ let t16;
610
+ if ($[41] !== t14) {
611
+ t16 = /* @__PURE__ */ jsx("button", {
612
+ type: "button",
613
+ "aria-label": t14,
614
+ onClick: closeEditor,
615
+ style: t15,
616
+ children: "×"
617
+ });
618
+ $[41] = t14;
619
+ $[42] = t16;
620
+ } else t16 = $[42];
621
+ let t17;
622
+ if ($[43] !== t13 || $[44] !== t16) {
623
+ t17 = /* @__PURE__ */ jsxs("div", {
624
+ style: headerStyle,
625
+ children: [t13, t16]
626
+ });
627
+ $[43] = t13;
628
+ $[44] = t16;
629
+ $[45] = t17;
630
+ } else t17 = $[45];
631
+ let t18;
632
+ if ($[46] === Symbol.for("react.memo_cache_sentinel")) {
633
+ t18 = /* @__PURE__ */ jsx("div", {
634
+ ref: hostRef,
635
+ style: hostStyle
636
+ });
637
+ $[46] = t18;
638
+ } else t18 = $[46];
639
+ let t19;
640
+ if ($[47] !== t11 || $[48] !== t17 || $[49] !== title) {
641
+ t19 = /* @__PURE__ */ jsxs("aside", {
642
+ style: t11,
643
+ "aria-label": title,
644
+ onKeyDown: t12,
645
+ children: [t17, t18]
646
+ });
647
+ $[47] = t11;
648
+ $[48] = t17;
649
+ $[49] = title;
650
+ $[50] = t19;
651
+ } else t19 = $[50];
652
+ return t19;
653
+ });
654
+ NoteStoryEditor.displayName = "NoteStoryEditor";
655
+ //#endregion
364
656
  //#region src/utils/contained-handler.ts
365
657
  /**
366
658
  * Wrap a React event handler so it only fires when the event target
@@ -403,7 +695,7 @@ const containedHandler = (handler) => (event) => {
403
695
  };
404
696
  //#endregion
405
697
  //#region src/paged-editor/AISuggestionRectsOverlay.tsx
406
- const overlayStyles$5 = {
698
+ const overlayStyles$6 = {
407
699
  position: "absolute",
408
700
  top: 0,
409
701
  left: "50%",
@@ -425,14 +717,14 @@ const AISuggestionRectsOverlay = (t0) => {
425
717
  if (groups.length === 0) return null;
426
718
  let t1;
427
719
  if ($[0] !== groups) {
428
- t1 = groups.map(_temp$9);
720
+ t1 = groups.map(_temp$10);
429
721
  $[0] = groups;
430
722
  $[1] = t1;
431
723
  } else t1 = $[1];
432
724
  let t2;
433
725
  if ($[2] !== t1) {
434
726
  t2 = /* @__PURE__ */ jsx("div", {
435
- style: overlayStyles$5,
727
+ style: overlayStyles$6,
436
728
  "data-folio-ai-suggestions-overlay": "",
437
729
  children: t1
438
730
  });
@@ -441,7 +733,7 @@ const AISuggestionRectsOverlay = (t0) => {
441
733
  } else t2 = $[3];
442
734
  return t2;
443
735
  };
444
- function _temp$9(t0) {
736
+ function _temp$10(t0) {
445
737
  const { suggestion, rects, focused, font } = t0;
446
738
  const replacementAnchor = rects.at(-1);
447
739
  const showReplacement = focused && suggestion.suggestedText.length > 0 && replacementAnchor !== void 0;
@@ -502,7 +794,7 @@ function _temp$9(t0) {
502
794
  * `selectionSeq` changes — repeated clicks of the same
503
795
  * canonical in the sidebar re-trigger the scroll).
504
796
  */
505
- const overlayStyles$4 = {
797
+ const overlayStyles$5 = {
506
798
  position: "absolute",
507
799
  top: 0,
508
800
  left: "50%",
@@ -562,7 +854,7 @@ const AnonymizationRectsOverlay = ({ groups, onTermClick, selectedCanonical = nu
562
854
  if (groups.length === 0) return null;
563
855
  return /* @__PURE__ */ jsx("div", {
564
856
  ref: overlayRef,
565
- style: overlayStyles$4,
857
+ style: overlayStyles$5,
566
858
  "data-folio-anonymization-overlay": "",
567
859
  children: groups.flatMap((group) => {
568
860
  const isSelected = selectedCanonical === group.canonical;
@@ -592,7 +884,7 @@ const AnonymizationRectsOverlay = ({ groups, onTermClick, selectedCanonical = nu
592
884
  };
593
885
  //#endregion
594
886
  //#region src/paged-editor/AutocompleteCaretOverlay.tsx
595
- const overlayStyles$3 = {
887
+ const overlayStyles$4 = {
596
888
  position: "absolute",
597
889
  top: 0,
598
890
  left: "50%",
@@ -643,7 +935,7 @@ const AutocompleteCaretOverlay = (t0) => {
643
935
  let t6;
644
936
  if ($[9] !== t3 || $[10] !== t5 || $[11] !== text) {
645
937
  t6 = /* @__PURE__ */ jsx("div", {
646
- style: overlayStyles$3,
938
+ style: overlayStyles$4,
647
939
  "data-folio-autocomplete-overlay": "",
648
940
  children: /* @__PURE__ */ jsxs("span", {
649
941
  className: "folio-autocomplete-ghost",
@@ -659,6 +951,52 @@ const AutocompleteCaretOverlay = (t0) => {
659
951
  return t6;
660
952
  };
661
953
  //#endregion
954
+ //#region src/paged-editor/PassageHighlightOverlay.tsx
955
+ const overlayStyles$3 = {
956
+ position: "absolute",
957
+ top: 0,
958
+ left: "50%",
959
+ width: "100vw",
960
+ height: "100%",
961
+ transform: "translateX(-50%)",
962
+ pointerEvents: "none",
963
+ zIndex: 1
964
+ };
965
+ const PassageHighlightOverlay = (t0) => {
966
+ const $ = c(4);
967
+ const { rects } = t0;
968
+ if (rects.length === 0) return null;
969
+ let t1;
970
+ if ($[0] !== rects) {
971
+ t1 = rects.map(_temp$9);
972
+ $[0] = rects;
973
+ $[1] = t1;
974
+ } else t1 = $[1];
975
+ let t2;
976
+ if ($[2] !== t1) {
977
+ t2 = /* @__PURE__ */ jsx("div", {
978
+ style: overlayStyles$3,
979
+ "data-folio-passage-highlight-overlay": "",
980
+ children: t1
981
+ });
982
+ $[2] = t1;
983
+ $[3] = t2;
984
+ } else t2 = $[3];
985
+ return t2;
986
+ };
987
+ function _temp$9(rect, idx) {
988
+ return /* @__PURE__ */ jsx("span", {
989
+ className: "folio-passage-highlight",
990
+ style: {
991
+ position: "absolute",
992
+ left: rect.x,
993
+ top: rect.y,
994
+ width: rect.width,
995
+ height: rect.height
996
+ }
997
+ }, `${idx}:${rect.pageIndex}:${rect.x}:${rect.y}`);
998
+ }
999
+ //#endregion
662
1000
  //#region src/paged-editor/embeddedFonts.ts
663
1001
  /**
664
1002
  * Registers a document's embedded fonts with the browser via the `FontFace`
@@ -669,6 +1007,10 @@ const AutocompleteCaretOverlay = (t0) => {
669
1007
  * `FontFace` handles so the caller can remove them on document change/unmount,
670
1008
  * preventing one document's embedded family from bleeding into the next.
671
1009
  */
1010
+ const EMPTY_LOADED_EMBEDDED_FONTS = {
1011
+ faces: [],
1012
+ familyMap: /* @__PURE__ */ new Map()
1013
+ };
672
1014
  function getDocumentFontSet$1() {
673
1015
  if (typeof document === "undefined" || !("fonts" in document)) return null;
674
1016
  return document.fonts;
@@ -701,14 +1043,14 @@ async function registerFontFace(fontSet, family, source, descriptors) {
701
1043
  */
702
1044
  async function loadEmbeddedFontFaces(buffer) {
703
1045
  const fontSet = getDocumentFontSet$1();
704
- if (!fontSet) return [];
1046
+ if (!fontSet) return EMPTY_LOADED_EMBEDDED_FONTS;
705
1047
  let fonts;
706
1048
  try {
707
1049
  fonts = await extractEmbeddedFonts(buffer);
708
1050
  } catch {
709
- return [];
1051
+ return EMPTY_LOADED_EMBEDDED_FONTS;
710
1052
  }
711
- if (fonts.length === 0) return [];
1053
+ if (fonts.length === 0) return EMPTY_LOADED_EMBEDDED_FONTS;
712
1054
  const loaded = [];
713
1055
  await Promise.all(fonts.map(async (font) => {
714
1056
  const face = await registerFontFace(fontSet, font.family, font.bytes, {
@@ -717,7 +1059,10 @@ async function loadEmbeddedFontFaces(buffer) {
717
1059
  });
718
1060
  if (face) loaded.push(face);
719
1061
  }));
720
- return loaded;
1062
+ return {
1063
+ faces: loaded,
1064
+ familyMap: buildEmbeddedFontFamilyMap(fonts)
1065
+ };
721
1066
  }
722
1067
  /** Remove previously registered faces from the document font set. */
723
1068
  function removeFontFaces(faces) {
@@ -764,6 +1109,7 @@ function toFontFaceInputs(fonts) {
764
1109
  if (!isValidFontDefinition(font)) continue;
765
1110
  const descriptors = { display: "swap" };
766
1111
  if (typeof font.weight === "number" || typeof font.weight === "string") descriptors.weight = String(font.weight);
1112
+ if (isNonEmptyString$1(font.style)) descriptors.style = font.style.trim();
767
1113
  inputs.push({
768
1114
  family: font.family.trim(),
769
1115
  source: `url(${JSON.stringify(font.src.trim())})`,
@@ -843,7 +1189,7 @@ const HIDDEN_HOST_STYLES = {
843
1189
  * HiddenProseMirror - Off-screen ProseMirror editor for keyboard input
844
1190
  */
845
1191
  const HiddenProseMirror = forwardRef((props, ref) => {
846
- const { document, documentKey, styles, theme: _theme, widthPx = 612, readOnly = false, onTransaction, onSelectionChange, externalPlugins = EMPTY_EXTERNAL_PLUGINS, collaboration, extensionManager, onEditorViewReady, onEditorViewDestroy, onKeyDown, onReadOnlyEditAttempt, onRemoteSelectionsChange, precomputedInitialState } = props;
1192
+ const { document, documentKey, styles, theme: _theme, widthPx = 612, readOnly = false, onTransaction, onSelectionChange, externalPlugins = EMPTY_EXTERNAL_PLUGINS, collaboration, extensionManager, onEditorViewReady, onEditorViewDestroy, onKeyDown, onCopy, onCut, onPaste, onReadOnlyEditAttempt, onRemoteSelectionsChange, precomputedInitialState } = props;
847
1193
  const [collaborationModules, setCollaborationModules] = useState(null);
848
1194
  const [collaborationModulesError, setCollaborationModulesError] = useState(null);
849
1195
  const hasCollaboration = collaboration !== void 0;
@@ -862,6 +1208,9 @@ const HiddenProseMirror = forwardRef((props, ref) => {
862
1208
  const onEditorViewReadyRef = useRef(onEditorViewReady);
863
1209
  const onEditorViewDestroyRef = useRef(onEditorViewDestroy);
864
1210
  const onKeyDownRef = useRef(onKeyDown);
1211
+ const onCopyRef = useRef(onCopy);
1212
+ const onCutRef = useRef(onCut);
1213
+ const onPasteRef = useRef(onPaste);
865
1214
  const onReadOnlyEditAttemptRef = useRef(onReadOnlyEditAttempt);
866
1215
  const onRemoteSelectionsChangeRef = useRef(onRemoteSelectionsChange);
867
1216
  readOnlyRef.current = readOnly;
@@ -874,6 +1223,9 @@ const HiddenProseMirror = forwardRef((props, ref) => {
874
1223
  onEditorViewReadyRef.current = onEditorViewReady;
875
1224
  onEditorViewDestroyRef.current = onEditorViewDestroy;
876
1225
  onKeyDownRef.current = onKeyDown;
1226
+ onCopyRef.current = onCopy;
1227
+ onCutRef.current = onCut;
1228
+ onPasteRef.current = onPaste;
877
1229
  onReadOnlyEditAttemptRef.current = onReadOnlyEditAttempt;
878
1230
  onRemoteSelectionsChangeRef.current = onRemoteSelectionsChange;
879
1231
  collaborationRef.current = collaboration;
@@ -896,6 +1248,9 @@ const HiddenProseMirror = forwardRef((props, ref) => {
896
1248
  onTransaction: (transaction, newState) => onTransactionRef.current?.(transaction, newState),
897
1249
  onSelectionChange: (state) => onSelectionChangeRef.current?.(state),
898
1250
  onKeyDown: (view, event) => onKeyDownRef.current?.(view, event) ?? false,
1251
+ onCopy: () => onCopyRef.current?.(),
1252
+ onCut: () => onCutRef.current?.(),
1253
+ onPaste: () => onPasteRef.current?.(),
899
1254
  onReadOnlyEditAttempt: () => onReadOnlyEditAttemptRef.current?.(),
900
1255
  onEditorViewReady: (view_0) => onEditorViewReadyRef.current?.(view_0),
901
1256
  onEditorViewDestroy: () => onEditorViewDestroyRef.current?.(),
@@ -2697,6 +3052,7 @@ function buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, doc) {
2697
3052
  const text = getFootnoteText(fn);
2698
3053
  items.push({
2699
3054
  displayNumber: String(displayNum),
3055
+ noteId: fnId,
2700
3056
  text,
2701
3057
  ...content ? { content: {
2702
3058
  blocks: content.blocks,
@@ -2713,7 +3069,7 @@ function buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, doc) {
2713
3069
  * PagedEditor - Main paginated editing component.
2714
3070
  */
2715
3071
  const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2716
- const { document, documentKey, fonts: hostFonts, styles, theme: _theme, sectionProperties, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, readOnly = false, pageGap = 24, zoom = 1, onDocumentChange, onReadOnlyEditAttempt, onSelectionChange, onSelectionTextChange, onEditorViewReady, externalPlugins = EMPTY_PLUGINS, showTemplateDirectives = true, collaboration, extensionManager, onHeaderFooterDoubleClick, hfEditMode, onBodyClick, className, style, commentsSidebarOpen = false, sidebarOverlay, scrollContainerRef: scrollContainerRefProp, onHyperlinkClick, onContextMenu, onAnchorPositionsChange, onTotalPagesChange, anchorPositionMode = "comments-and-revisions", onAnonymizationTermClick, selectedAnonymizationCanonical = null, anonymizationSelectionSeq } = props;
3072
+ const { document, documentKey, fonts: hostFonts, styles, theme: _theme, sectionProperties, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, readOnly = false, pageGap = 24, zoom = 1, showMarginGuides = false, marginGuideColor, onDocumentChange, onReadOnlyEditAttempt, onCopy, onCut, onPaste, onSelectionChange, onSelectionTextChange, onEditorViewReady, externalPlugins = EMPTY_PLUGINS, showTemplateDirectives = true, collaboration, extensionManager, suggestionModeActive = false, suggestionAuthor, onActiveNoteStoryChange, onHeaderFooterDoubleClick, hfEditMode, activeHeaderFooterRId, onBodyClick, className, style, commentsSidebarOpen = false, sidebarOverlay, scrollContainerRef: scrollContainerRefProp, onHyperlinkClick, onContextMenu, onAnchorPositionsChange, onTotalPagesChange, anchorPositionMode = "comments-and-revisions", onAnonymizationTermClick, selectedAnonymizationCanonical = null, anonymizationSelectionSeq } = props;
2717
3073
  const getScrollContainer = useCallback(() => {
2718
3074
  if (scrollContainerRefProp && typeof scrollContainerRefProp === "object") return scrollContainerRefProp.current;
2719
3075
  return containerRef.current;
@@ -2723,7 +3079,17 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2723
3079
  const folioEmitterRef = useRef(createFolioEditorEmitter());
2724
3080
  const hiddenPMRef = useRef(null);
2725
3081
  const hfPMsRef = useRef(null);
3082
+ const noteEditorRef = useRef(null);
3083
+ const [noteStoryActive, setNoteStoryActive] = useState(false);
2726
3084
  const painterRef = useRef(null);
3085
+ const noteStoryPlugins = useMemo(() => externalPlugins.filter(({ spec }) => spec.key === suggestionModeKey), [externalPlugins]);
3086
+ const handleActiveNoteStoryChange = useCallback((story) => {
3087
+ setNoteStoryActive(story !== null);
3088
+ onActiveNoteStoryChange?.(story);
3089
+ }, [onActiveNoteStoryChange]);
3090
+ useEffect(() => {
3091
+ if (readOnly) noteEditorRef.current?.close();
3092
+ }, [readOnly]);
2727
3093
  const { handlePMKeyDown } = useVisualLineNavigation({ pagesContainerRef });
2728
3094
  const handleHiddenEditorKeyDown = useCallback((view, event) => {
2729
3095
  if (getTemplateSlashMenu(view.state).active) return false;
@@ -2788,6 +3154,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2788
3154
  focusedId: null
2789
3155
  });
2790
3156
  const [aiSuggestionsOverlayRequestGate] = useState(createLatestRequestGate);
3157
+ const passageHighlightRangeRef = useRef(null);
3158
+ const [passageHighlightRects, setPassageHighlightRects] = useState([]);
3159
+ const [passageHighlightOverlayRequestGate] = useState(createLatestRequestGate);
2791
3160
  const [remoteSelections, setRemoteSelections] = useState([]);
2792
3161
  const suppressSelectionOverlayRef = useRef(false);
2793
3162
  const revealSelectionOverlayTimerRef = useRef(null);
@@ -2974,6 +3343,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2974
3343
  pageSize,
2975
3344
  margins,
2976
3345
  pageGap,
3346
+ showMarginGuides,
3347
+ marginGuideColor,
2977
3348
  syncCoordinator,
2978
3349
  headerContent,
2979
3350
  footerContent,
@@ -3017,6 +3388,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3017
3388
  margins,
3018
3389
  pageGap,
3019
3390
  zoom,
3391
+ showMarginGuides,
3392
+ marginGuideColor,
3020
3393
  syncCoordinator,
3021
3394
  headerContent,
3022
3395
  footerContent,
@@ -3044,6 +3417,27 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3044
3417
  emitter: folioEmitterRef.current
3045
3418
  });
3046
3419
  const folioEditor = folioEditorRef.current;
3420
+ const getActiveEditorStory = useCallback(() => resolveActiveEditorStory({
3421
+ bodyView: folioEditor.getView(),
3422
+ headerFooterView: hfEditMode && activeHeaderFooterRId ? hfPMsRef.current?.getView(activeHeaderFooterRId) ?? null : null,
3423
+ noteView: noteEditorRef.current?.getActiveView() ?? null
3424
+ }), [
3425
+ activeHeaderFooterRId,
3426
+ folioEditor,
3427
+ hfEditMode
3428
+ ]);
3429
+ const marginGuideSettingsInitializedRef = useRef(false);
3430
+ useEffect(() => {
3431
+ if (!marginGuideSettingsInitializedRef.current) {
3432
+ marginGuideSettingsInitializedRef.current = true;
3433
+ return;
3434
+ }
3435
+ folioEditor.relayout();
3436
+ }, [
3437
+ folioEditor,
3438
+ marginGuideColor,
3439
+ showMarginGuides
3440
+ ]);
3047
3441
  const layoutSchedulerRef = useRef(null);
3048
3442
  if (layoutSchedulerRef.current === null) layoutSchedulerRef.current = createLayoutScheduler({
3049
3443
  runLayout: (state_1, options_1) => runLayoutPipelineRef.current(state_1, options_1),
@@ -3531,6 +3925,41 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3531
3925
  measures,
3532
3926
  zoom
3533
3927
  ]);
3928
+ const updatePassageHighlightOverlay = useCallback(() => {
3929
+ const isCurrentRequest_4 = passageHighlightOverlayRequestGate.begin();
3930
+ const range_5 = passageHighlightRangeRef.current;
3931
+ const pagesContainer_3 = pagesContainerRef.current;
3932
+ if (range_5 === null || !pagesContainer_3) {
3933
+ setPassageHighlightRects((prev_0) => prev_0.length === 0 ? prev_0 : []);
3934
+ return;
3935
+ }
3936
+ (async () => {
3937
+ const projected_1 = await projectRangesToRects([range_5], {
3938
+ pagesContainer: pagesContainer_3,
3939
+ zoom,
3940
+ layout,
3941
+ blocks,
3942
+ measures
3943
+ });
3944
+ if (!isCurrentRequest_4()) return;
3945
+ setPassageHighlightRects(projected_1.at(0)?.rects ?? []);
3946
+ })();
3947
+ }, [
3948
+ passageHighlightOverlayRequestGate,
3949
+ layout,
3950
+ blocks,
3951
+ measures,
3952
+ zoom
3953
+ ]);
3954
+ const setPassageHighlightImpl = useCallback((range_6) => {
3955
+ passageHighlightRangeRef.current = range_6;
3956
+ if (range_6 === null) {
3957
+ passageHighlightOverlayRequestGate.invalidate();
3958
+ setPassageHighlightRects((prev_1) => prev_1.length === 0 ? prev_1 : []);
3959
+ return;
3960
+ }
3961
+ updatePassageHighlightOverlay();
3962
+ }, [passageHighlightOverlayRequestGate, updatePassageHighlightOverlay]);
3534
3963
  const hideSelectionOverlayDuringInput = useCallback((state_4) => {
3535
3964
  selectionOverlayRequestGate.invalidate();
3536
3965
  suppressSelectionOverlayRef.current = true;
@@ -3549,6 +3978,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3549
3978
  autocompleteOverlayRequestGate.invalidate();
3550
3979
  directivesOverlayRequestGate.invalidate();
3551
3980
  aiSuggestionsOverlayRequestGate.invalidate();
3981
+ passageHighlightOverlayRequestGate.invalidate();
3552
3982
  if (revealSelectionOverlayTimerRef.current !== null) {
3553
3983
  window.clearTimeout(revealSelectionOverlayTimerRef.current);
3554
3984
  revealSelectionOverlayTimerRef.current = null;
@@ -3558,6 +3988,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3558
3988
  anonymizationOverlayRequestGate,
3559
3989
  autocompleteOverlayRequestGate,
3560
3990
  directivesOverlayRequestGate,
3991
+ passageHighlightOverlayRequestGate,
3561
3992
  selectionOverlayRequestGate
3562
3993
  ]);
3563
3994
  /**
@@ -3605,6 +4036,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3605
4036
  }
3606
4037
  if (transaction.docChanged) {
3607
4038
  syncCoordinator.incrementStateSeq();
4039
+ if (passageHighlightRangeRef.current !== null) {
4040
+ passageHighlightRangeRef.current = null;
4041
+ passageHighlightOverlayRequestGate.invalidate();
4042
+ setPassageHighlightRects((prev_2) => prev_2.length === 0 ? prev_2 : []);
4043
+ }
3608
4044
  hideSelectionOverlayDuringInput(newState);
3609
4045
  scheduleLayout(newState, getTransactionDirtyRange(transaction));
3610
4046
  scheduleDocumentChangeNotification();
@@ -3620,6 +4056,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3620
4056
  updateAutocompleteOverlay,
3621
4057
  updateDirectivesOverlay,
3622
4058
  updateAISuggestionsOverlay,
4059
+ passageHighlightOverlayRequestGate,
3623
4060
  syncCoordinator
3624
4061
  ]);
3625
4062
  /**
@@ -3666,6 +4103,24 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3666
4103
  });
3667
4104
  }
3668
4105
  }, [scheduleLayout, ensureHiddenEditorView]);
4106
+ const handleNoteStoryTransaction = useCallback((view_2, docChanged_0, selectionChanged_0) => {
4107
+ if (docChanged_0) {
4108
+ const bodyState_0 = hiddenPMRef.current?.getState();
4109
+ if (bodyState_0) scheduleLayout(bodyState_0, null);
4110
+ }
4111
+ if (docChanged_0 || selectionChanged_0) {
4112
+ const { from: from_2, to: to_2 } = view_2.state.selection;
4113
+ onSelectionChangeRef.current?.(from_2, to_2);
4114
+ folioEmitterRef.current.emit("selectionChange", {
4115
+ from: from_2,
4116
+ to: to_2
4117
+ });
4118
+ }
4119
+ }, [scheduleLayout]);
4120
+ const handleNoteDocumentChange = useCallback((updated) => {
4121
+ onDocumentChangeRef.current?.(updated);
4122
+ folioEmitterRef.current.emit("docChange", updated);
4123
+ }, []);
3669
4124
  useEffect(() => {
3670
4125
  if (!hfEditMode) setHfCaretSelection(null);
3671
4126
  dragAnchorRef.current = null;
@@ -3682,12 +4137,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3682
4137
  setCaretPosition(null);
3683
4138
  } else if (syncCoordinator.isSafeToRender()) updateSelectionOverlay(state_5);
3684
4139
  requestAnimationFrame(() => {
3685
- const view_2 = hiddenPMRef.current?.getView();
3686
- if (!view_2) {
4140
+ const view_3 = hiddenPMRef.current?.getView();
4141
+ if (!view_3) {
3687
4142
  setSelectedImageInfo(null);
3688
4143
  return;
3689
4144
  }
3690
- const { selection: sel_0 } = view_2.state;
4145
+ const { selection: sel_0 } = view_3.state;
3691
4146
  if (sel_0 instanceof NodeSelection && sel_0.node.type.name === "image") {
3692
4147
  const pmPos_2 = sel_0.from;
3693
4148
  const imgEl = pagesContainerRef.current ? findBodyPmAnchor(pagesContainerRef.current, pmPos_2) : null;
@@ -3763,9 +4218,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3763
4218
  return null;
3764
4219
  }, []);
3765
4220
  const findCellPosFromPmPos = useCallback((pmPos_4) => {
3766
- const view_3 = hiddenPMRef.current?.getView();
3767
- if (!view_3) return null;
3768
- return findCellPosInDoc(view_3.state.doc, pmPos_4);
4221
+ const view_4 = hiddenPMRef.current?.getView();
4222
+ if (!view_4) return null;
4223
+ return findCellPosInDoc(view_4.state.doc, pmPos_4);
3769
4224
  }, [findCellPosInDoc]);
3770
4225
  /**
3771
4226
  * Find the closest image element from a click target.
@@ -3853,10 +4308,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3853
4308
  cellDragAnchorPosRef.current = null;
3854
4309
  cellDragContentEndRef.current = null;
3855
4310
  isCellDraggingRef.current = false;
3856
- const view_4 = hiddenPMRef.current?.getView();
4311
+ const view_5 = hiddenPMRef.current?.getView();
3857
4312
  let endPos;
3858
- if (view_4) {
3859
- endPos = Math.max(0, view_4.state.doc.content.size - 1);
4313
+ if (view_5) {
4314
+ endPos = Math.max(0, view_5.state.doc.content.size - 1);
3860
4315
  hiddenPMRef.current?.setSelection(endPos);
3861
4316
  } else {
3862
4317
  endPos = Math.max(0, (precomputedInitialStateRef.current?.doc.content.size ?? 1) - 1);
@@ -3876,11 +4331,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3876
4331
  queueHiddenEditorSelection
3877
4332
  ]);
3878
4333
  const copySelectionText = useCallback(() => {
3879
- const view_5 = hiddenPMRef.current?.getView();
3880
- if (!view_5) return false;
3881
- const { from: from_2, to: to_2 } = view_5.state.selection;
3882
- if (from_2 === to_2) return false;
3883
- const text_1 = view_5.state.doc.textBetween(from_2, to_2, "\n");
4334
+ const view_6 = hiddenPMRef.current?.getView();
4335
+ if (!view_6) return false;
4336
+ const { from: from_3, to: to_3 } = view_6.state.selection;
4337
+ if (from_3 === to_3) return false;
4338
+ const text_1 = view_6.state.doc.textBetween(from_3, to_3, "\n");
3884
4339
  if (!text_1) return false;
3885
4340
  if (navigator.clipboard === void 0) return false;
3886
4341
  navigator.clipboard.writeText(text_1).catch(() => void 0);
@@ -3895,11 +4350,15 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3895
4350
  e.preventDefault();
3896
4351
  return;
3897
4352
  }
3898
- if (e.button !== 0) return;
4353
+ if (e.button !== 0) {
4354
+ if ((e.target instanceof HTMLElement ? e.target : null)?.closest("a[href]") instanceof HTMLAnchorElement) e.preventDefault();
4355
+ return;
4356
+ }
3899
4357
  setTableInsertButton(null);
3900
4358
  clearTableInsertTimer();
3901
4359
  const target_1 = e.target instanceof HTMLElement ? e.target : null;
3902
4360
  if (!target_1) return;
4361
+ noteEditorRef.current?.close();
3903
4362
  const anchorClosest = target_1.closest("a[href]");
3904
4363
  if (anchorClosest instanceof HTMLAnchorElement ? anchorClosest : null) e.preventDefault();
3905
4364
  if (!readOnly && hfEditMode && onBodyClick) {
@@ -3973,9 +4432,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3973
4432
  const colIndex = Number.parseInt(target_1.dataset["columnIndex"] ?? "0", 10);
3974
4433
  resizeColumnIndexRef.current = colIndex;
3975
4434
  resizeTablePmStartRef.current = Number.parseInt(target_1.dataset["tablePmStart"] ?? "0", 10);
3976
- const view_6 = resizeViewForRead;
3977
- if (view_6) {
3978
- const $pos_1 = view_6.state.doc.resolve(resizeTablePmStartRef.current + 1);
4435
+ const view_7 = resizeViewForRead;
4436
+ if (view_7) {
4437
+ const $pos_1 = view_7.state.doc.resolve(resizeTablePmStartRef.current + 1);
3979
4438
  for (let d_0 = $pos_1.depth; d_0 >= 0; d_0--) {
3980
4439
  const node_1 = $pos_1.node(d_0);
3981
4440
  if (node_1.type.name === "table") {
@@ -4005,9 +4464,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4005
4464
  const rowIndex = Number.parseInt(target_1.dataset["rowIndex"] ?? "0", 10);
4006
4465
  resizeRowIndexRef.current = rowIndex;
4007
4466
  resizeRowTablePmStartRef.current = Number.parseInt(target_1.dataset["tablePmStart"] ?? "0", 10);
4008
- const view_7 = resizeViewForRead;
4009
- if (view_7) {
4010
- const $pos_2 = view_7.state.doc.resolve(resizeRowTablePmStartRef.current + 1);
4467
+ const view_8 = resizeViewForRead;
4468
+ if (view_8) {
4469
+ const $pos_2 = view_8.state.doc.resolve(resizeRowTablePmStartRef.current + 1);
4011
4470
  for (let d_1 = $pos_2.depth; d_1 >= 0; d_1--) {
4012
4471
  const node_2 = $pos_2.node(d_1);
4013
4472
  if (node_2.type.name === "table") {
@@ -4040,9 +4499,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4040
4499
  const colIndex_0 = Number.parseInt(target_1.dataset["columnIndex"] ?? "0", 10);
4041
4500
  resizeRightEdgeColIndexRef.current = colIndex_0;
4042
4501
  resizeRightEdgePmStartRef.current = Number.parseInt(target_1.dataset["tablePmStart"] ?? "0", 10);
4043
- const view_8 = resizeViewForRead;
4044
- if (view_8) {
4045
- const $pos_3 = view_8.state.doc.resolve(resizeRightEdgePmStartRef.current + 1);
4502
+ const view_9 = resizeViewForRead;
4503
+ if (view_9) {
4504
+ const $pos_3 = view_9.state.doc.resolve(resizeRightEdgePmStartRef.current + 1);
4046
4505
  for (let d_2 = $pos_3.depth; d_2 >= 0; d_2--) {
4047
4506
  const node_3 = $pos_3.node(d_2);
4048
4507
  if (node_3.type.name === "table") {
@@ -4241,18 +4700,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4241
4700
  resizeHandleRef.current.classList.remove("dragging");
4242
4701
  resizeHandleRef.current = null;
4243
4702
  }
4244
- const view_9 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4703
+ const view_10 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4245
4704
  resizingHfSurfaceRef.current = null;
4246
- if (view_9) {
4705
+ if (view_10) {
4247
4706
  const pmStart_4 = resizeTablePmStartRef.current;
4248
4707
  const colIdx = resizeColumnIndexRef.current;
4249
4708
  const { left: newLeft, right: newRight } = resizeOrigWidthsRef.current;
4250
- const $pos_5 = view_9.state.doc.resolve(pmStart_4 + 1);
4709
+ const $pos_5 = view_10.state.doc.resolve(pmStart_4 + 1);
4251
4710
  for (let d_3 = $pos_5.depth; d_3 >= 0; d_3--) {
4252
4711
  const node_4 = $pos_5.node(d_3);
4253
4712
  if (node_4.type.name === "table") {
4254
4713
  const tablePos = $pos_5.before(d_3);
4255
- const tr = view_9.state.tr;
4714
+ const tr = view_10.state.tr;
4256
4715
  const tableAttrs = expectTableAttrs(node_4);
4257
4716
  if (!tableAttrs.columnWidths) break;
4258
4717
  const widths_1 = [...tableAttrs.columnWidths];
@@ -4278,7 +4737,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4278
4737
  });
4279
4738
  rowOffset += row.nodeSize;
4280
4739
  });
4281
- view_9.dispatch(tr);
4740
+ view_10.dispatch(tr);
4282
4741
  break;
4283
4742
  }
4284
4743
  }
@@ -4291,18 +4750,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4291
4750
  resizeRowHandleRef.current.classList.remove("dragging");
4292
4751
  resizeRowHandleRef.current = null;
4293
4752
  }
4294
- const view_10 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4753
+ const view_11 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4295
4754
  resizingHfSurfaceRef.current = null;
4296
- if (view_10) {
4755
+ if (view_11) {
4297
4756
  const pmStart_5 = resizeRowTablePmStartRef.current;
4298
4757
  const rowIdx = resizeRowIndexRef.current;
4299
4758
  const newHeight_0 = resizeRowOrigHeightRef.current;
4300
- const $pos_6 = view_10.state.doc.resolve(pmStart_5 + 1);
4759
+ const $pos_6 = view_11.state.doc.resolve(pmStart_5 + 1);
4301
4760
  for (let d_4 = $pos_6.depth; d_4 >= 0; d_4--) {
4302
4761
  const node_5 = $pos_6.node(d_4);
4303
4762
  if (node_5.type.name === "table") {
4304
4763
  const tablePos_0 = $pos_6.before(d_4);
4305
- const tr_0 = view_10.state.tr;
4764
+ const tr_0 = view_11.state.tr;
4306
4765
  let rowOffset_0 = tablePos_0 + 1;
4307
4766
  let idx = 0;
4308
4767
  node_5.forEach((row_0) => {
@@ -4313,7 +4772,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4313
4772
  rowOffset_0 += row_0.nodeSize;
4314
4773
  idx++;
4315
4774
  });
4316
- view_10.dispatch(tr_0);
4775
+ view_11.dispatch(tr_0);
4317
4776
  break;
4318
4777
  }
4319
4778
  }
@@ -4326,18 +4785,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4326
4785
  resizeRightEdgeHandleRef.current.classList.remove("dragging");
4327
4786
  resizeRightEdgeHandleRef.current = null;
4328
4787
  }
4329
- const view_11 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4788
+ const view_12 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4330
4789
  resizingHfSurfaceRef.current = null;
4331
- if (view_11) {
4790
+ if (view_12) {
4332
4791
  const pmStart_6 = resizeRightEdgePmStartRef.current;
4333
4792
  const colIdx_0 = resizeRightEdgeColIndexRef.current;
4334
4793
  const newWidth_1 = resizeRightEdgeOrigWidthRef.current;
4335
- const $pos_7 = view_11.state.doc.resolve(pmStart_6 + 1);
4794
+ const $pos_7 = view_12.state.doc.resolve(pmStart_6 + 1);
4336
4795
  for (let d_5 = $pos_7.depth; d_5 >= 0; d_5--) {
4337
4796
  const node_6 = $pos_7.node(d_5);
4338
4797
  if (node_6.type.name === "table") {
4339
4798
  const tablePos_1 = $pos_7.before(d_5);
4340
- const tr_1 = view_11.state.tr;
4799
+ const tr_1 = view_12.state.tr;
4341
4800
  const tableAttrs_0 = expectTableAttrs(node_6);
4342
4801
  if (!tableAttrs_0.columnWidths) break;
4343
4802
  const widths_2 = [...tableAttrs_0.columnWidths];
@@ -4359,7 +4818,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4359
4818
  });
4360
4819
  rowOffset_1 += row_1.nodeSize;
4361
4820
  });
4362
- view_11.dispatch(tr_1);
4821
+ view_12.dispatch(tr_1);
4363
4822
  break;
4364
4823
  }
4365
4824
  }
@@ -4501,13 +4960,13 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4501
4960
  e_2.preventDefault();
4502
4961
  e_2.stopPropagation();
4503
4962
  if (!tableInsertButton || !hiddenPMRef.current) return;
4504
- const view_12 = hiddenPMRef.current.getView();
4505
- if (!view_12) return;
4963
+ const view_13 = hiddenPMRef.current.getView();
4964
+ if (!view_13) return;
4506
4965
  const { type, cellPmPos } = tableInsertButton;
4507
- const tr_2 = view_12.state.tr.setSelection(TextSelection$1.create(view_12.state.doc, cellPmPos + 1));
4508
- view_12.dispatch(tr_2);
4509
- if (type === "row") addRowBelow(view_12.state, view_12.dispatch);
4510
- else addColumnRight(view_12.state, view_12.dispatch);
4966
+ const tr_2 = view_13.state.tr.setSelection(TextSelection$1.create(view_13.state.doc, cellPmPos + 1));
4967
+ view_13.dispatch(tr_2);
4968
+ if (type === "row") addRowBelow(view_13.state, view_13.dispatch);
4969
+ else addColumnRight(view_13.state, view_13.dispatch);
4511
4970
  setTableInsertButton(null);
4512
4971
  hiddenPMRef.current.focus();
4513
4972
  }, [tableInsertButton]);
@@ -4517,6 +4976,15 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4517
4976
  const handlePagesClick = useCallback((e_3) => {
4518
4977
  const target_2 = e_3.target instanceof HTMLElement ? e_3.target : null;
4519
4978
  if (!target_2) return;
4979
+ if (!readOnly && e_3.detail === 2) {
4980
+ const story_0 = findNoteStoryForTarget(target_2);
4981
+ if (story_0) {
4982
+ e_3.preventDefault();
4983
+ e_3.stopPropagation();
4984
+ noteEditorRef.current?.open(story_0);
4985
+ return;
4986
+ }
4987
+ }
4520
4988
  const anchorClosest_0 = target_2.closest("a[href]");
4521
4989
  const anchorEl_0 = anchorClosest_0 instanceof HTMLAnchorElement ? anchorClosest_0 : null;
4522
4990
  if (anchorEl_0) {
@@ -4525,10 +4993,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4525
4993
  if (href.startsWith("#")) {
4526
4994
  const bookmarkName = href.slice(1);
4527
4995
  if (bookmarkName && hiddenPMRef.current) {
4528
- const view_13 = hiddenPMRef.current.getView();
4529
- if (view_13) {
4996
+ const view_14 = hiddenPMRef.current.getView();
4997
+ if (view_14) {
4530
4998
  const targetPos = { value: null };
4531
- view_13.state.doc.descendants((node_7, pos_2) => {
4999
+ view_14.state.doc.descendants((node_7, pos_2) => {
4532
5000
  if (targetPos.value !== null) return false;
4533
5001
  if (node_7.type.name === "paragraph") {
4534
5002
  if (node_7.attrs["bookmarks"]?.some((b) => b.name === bookmarkName)) {
@@ -4617,9 +5085,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4617
5085
  if (e_3.detail === 2 && hiddenPMRef.current) {
4618
5086
  const pmPos_12 = getPositionFromMouse(e_3.clientX, e_3.clientY);
4619
5087
  if (pmPos_12 !== null) {
4620
- const view_14 = hiddenPMRef.current.getView();
4621
- if (view_14) {
4622
- const { doc: doc_0 } = view_14.state;
5088
+ const view_15 = hiddenPMRef.current.getView();
5089
+ if (view_15) {
5090
+ const { doc: doc_0 } = view_15.state;
4623
5091
  const $pos_9 = doc_0.resolve(pmPos_12);
4624
5092
  const parent_0 = $pos_9.parent;
4625
5093
  if (parent_0.isTextblock) {
@@ -4645,9 +5113,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4645
5113
  if (e_3.detail === 3 && hiddenPMRef.current) {
4646
5114
  const pmPos_13 = getPositionFromMouse(e_3.clientX, e_3.clientY);
4647
5115
  if (pmPos_13 !== null) {
4648
- const view_15 = hiddenPMRef.current.getView();
4649
- if (view_15) {
4650
- const { doc: doc_1 } = view_15.state;
5116
+ const view_16 = hiddenPMRef.current.getView();
5117
+ if (view_16) {
5118
+ const { doc: doc_1 } = view_16.state;
4651
5119
  const $pos_10 = doc_1.resolve(pmPos_13);
4652
5120
  const paragraphStart = $pos_10.start($pos_10.depth);
4653
5121
  const paragraphEnd = $pos_10.end($pos_10.depth);
@@ -4673,9 +5141,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4673
5141
  if (slot_2) {
4674
5142
  const hfView_4 = hfPMsRef.current?.getView(slot_2.rId);
4675
5143
  if (hfView_4) {
4676
- const { from: from_3, to: to_3 } = hfView_4.state.selection;
5144
+ const { from: from_4, to: to_4 } = hfView_4.state.selection;
4677
5145
  const pmPos_14 = clickToPositionInHfSlot(pagesContainerRef.current ?? slot_2.element, slot_2.kind, slot_2.rId, e_4.clientX, e_4.clientY);
4678
- if (pmPos_14 !== null && (from_3 === to_3 || pmPos_14 < from_3 || pmPos_14 > to_3)) {
5146
+ if (pmPos_14 !== null && (from_4 === to_4 || pmPos_14 < from_4 || pmPos_14 > to_4)) {
4679
5147
  const docEnd_3 = hfView_4.state.doc.content.size;
4680
5148
  const clamped_1 = Math.max(0, Math.min(pmPos_14, docEnd_3));
4681
5149
  const $pos_11 = hfView_4.state.doc.resolve(clamped_1);
@@ -4692,11 +5160,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4692
5160
  }
4693
5161
  }
4694
5162
  }
4695
- const view_16 = hiddenPMRef.current?.getView();
4696
- if (!view_16) return;
4697
- const { from: from_4, to: to_4 } = view_16.state.selection;
5163
+ const view_17 = hiddenPMRef.current?.getView();
5164
+ if (!view_17) return;
5165
+ const { from: from_5, to: to_5 } = view_17.state.selection;
4698
5166
  const pmPos_15 = getPositionFromMouse(e_4.clientX, e_4.clientY);
4699
- if (pmPos_15 !== null && (from_4 === to_4 || pmPos_15 < from_4 || pmPos_15 > to_4)) {
5167
+ if (pmPos_15 !== null && (from_5 === to_5 || pmPos_15 < from_5 || pmPos_15 > to_5)) {
4700
5168
  hiddenPMRef.current?.setSelection(pmPos_15);
4701
5169
  hiddenPMRef.current?.focus();
4702
5170
  setIsFocused(true);
@@ -4719,7 +5187,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4719
5187
  */
4720
5188
  const handleContainerFocus = useCallback((e_5) => {
4721
5189
  if (e_5.target instanceof HTMLElement && e_5.target.closest(".docx-comments-sidebar")) return;
4722
- if (e_5.target instanceof HTMLElement && e_5.target.closest("[data-hf-r-id]")) return;
5190
+ if (e_5.target instanceof HTMLElement && e_5.target.closest("[data-hf-r-id], [data-note-kind][data-note-id]")) return;
4723
5191
  focusHiddenEditor();
4724
5192
  }, [focusHiddenEditor]);
4725
5193
  /**
@@ -4735,16 +5203,16 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4735
5203
  * Handle image resize from the overlay.
4736
5204
  */
4737
5205
  const handleImageResize = useCallback((pmPos_16, newWidth_2, newHeight_1) => {
4738
- const view_17 = hiddenPMRef.current?.getView();
4739
- if (!view_17) return;
5206
+ const view_18 = hiddenPMRef.current?.getView();
5207
+ if (!view_18) return;
4740
5208
  try {
4741
- const node_10 = view_17.state.doc.nodeAt(pmPos_16);
5209
+ const node_10 = view_18.state.doc.nodeAt(pmPos_16);
4742
5210
  if (!node_10 || node_10.type.name !== "image") return;
4743
- const tr_3 = view_17.state.tr.setNodeMarkup(pmPos_16, void 0, mergeImageAttrs(node_10, {
5211
+ const tr_3 = view_18.state.tr.setNodeMarkup(pmPos_16, void 0, mergeImageAttrs(node_10, {
4744
5212
  width: newWidth_2,
4745
5213
  height: newHeight_1
4746
5214
  }));
4747
- view_17.dispatch(tr_3);
5215
+ view_18.dispatch(tr_3);
4748
5216
  hiddenPMRef.current?.setNodeSelection(pmPos_16);
4749
5217
  } catch {}
4750
5218
  }, []);
@@ -4765,10 +5233,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4765
5233
  * to the drop position determined by mouse coordinates.
4766
5234
  */
4767
5235
  const handleImageDragMove = useCallback((pmPos_17, clientX_1, clientY_1) => {
4768
- const view_18 = hiddenPMRef.current?.getView();
4769
- if (!view_18) return;
5236
+ const view_19 = hiddenPMRef.current?.getView();
5237
+ if (!view_19) return;
4770
5238
  try {
4771
- const node_11 = view_18.state.doc.nodeAt(pmPos_17);
5239
+ const node_11 = view_19.state.doc.nodeAt(pmPos_17);
4772
5240
  if (!node_11 || node_11.type.name !== "image") return;
4773
5241
  const attrs = expectImageAttrs(node_11);
4774
5242
  if (attrs.displayMode === "float" || attrs.wrapType === "square" || attrs.wrapType === "tight" || attrs.wrapType === "through") {
@@ -4803,14 +5271,14 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4803
5271
  relativeTo: "margin"
4804
5272
  }
4805
5273
  };
4806
- const tr_4 = view_18.state.tr.setNodeMarkup(pmPos_17, void 0, mergeImageAttrs(node_11, { position: newPosition }));
4807
- view_18.dispatch(tr_4);
5274
+ const tr_4 = view_19.state.tr.setNodeMarkup(pmPos_17, void 0, mergeImageAttrs(node_11, { position: newPosition }));
5275
+ view_19.dispatch(tr_4);
4808
5276
  hiddenPMRef.current?.setNodeSelection(pmPos_17);
4809
5277
  } else {
4810
5278
  const dropPos = getPositionFromMouse(clientX_1, clientY_1);
4811
5279
  if (dropPos === null) return;
4812
5280
  if (dropPos === pmPos_17 || dropPos === pmPos_17 + 1) return;
4813
- let tr_5 = view_18.state.tr;
5281
+ let tr_5 = view_19.state.tr;
4814
5282
  tr_5 = tr_5.delete(pmPos_17, pmPos_17 + node_11.nodeSize);
4815
5283
  let selectionPos;
4816
5284
  if (dropPos <= pmPos_17) {
@@ -4822,7 +5290,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4822
5290
  selectionPos = Math.min(adjusted, tr_5.doc.content.size - 1);
4823
5291
  }
4824
5292
  hiddenPMRef.current?.setNodeSelection(selectionPos);
4825
- view_18.dispatch(tr_5);
5293
+ view_19.dispatch(tr_5);
4826
5294
  }
4827
5295
  } catch {}
4828
5296
  }, [getPositionFromMouse, zoom]);
@@ -4849,12 +5317,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4849
5317
  }
4850
5318
  return;
4851
5319
  }
4852
- if (e_7.target instanceof HTMLElement && e_7.target.closest("[data-hf-r-id]")) return;
4853
- let view_19 = hiddenPMRef.current?.getView();
4854
- if (!view_19) {
5320
+ if (e_7.target instanceof HTMLElement && e_7.target.closest("[data-hf-r-id], [data-note-kind][data-note-id]")) return;
5321
+ let view_20 = hiddenPMRef.current?.getView();
5322
+ if (!view_20) {
4855
5323
  ensureHiddenEditorView({ sync: true });
4856
- view_19 = hiddenPMRef.current?.getView();
4857
- if (view_19) {
5324
+ view_20 = hiddenPMRef.current?.getView();
5325
+ if (view_20) {
4858
5326
  if (isPlainTextInputEvent(e_7)) {
4859
5327
  e_7.preventDefault();
4860
5328
  queueHiddenEditorTextInput(e_7.key);
@@ -4877,11 +5345,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4877
5345
  }
4878
5346
  return;
4879
5347
  }
4880
- if (pendingHiddenEditorSelectionRef.current || queuedInputBeforeHiddenEditorRef.current.length > 0) applyPendingHiddenEditorInput(view_19);
5348
+ if (pendingHiddenEditorSelectionRef.current || queuedInputBeforeHiddenEditorRef.current.length > 0) applyPendingHiddenEditorInput(view_20);
4881
5349
  if (!hiddenPMRef.current?.isFocused()) focusHiddenEditor();
4882
5350
  if (e_7.key === " " && !e_7.ctrlKey && !e_7.metaKey && !e_7.nativeEvent.isComposing) {
4883
5351
  e_7.preventDefault();
4884
- dispatchEditorTextInput(view_19, " ");
5352
+ dispatchEditorTextInput(view_20, " ");
4885
5353
  return;
4886
5354
  }
4887
5355
  if (["PageUp", "PageDown"].includes(e_7.key) && !e_7.metaKey && !e_7.ctrlKey) {}
@@ -4909,7 +5377,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4909
5377
  */
4910
5378
  const handleContainerMouseDown = useCallback((e_8) => {
4911
5379
  if (e_8.target instanceof HTMLElement && e_8.target.closest(".docx-comments-sidebar")) return;
4912
- if (e_8.target instanceof HTMLElement && e_8.target.closest("[data-hf-r-id]")) return;
5380
+ if (e_8.target instanceof HTMLElement && e_8.target.closest("[data-hf-r-id], [data-note-kind][data-note-id]")) return;
4913
5381
  if (!hiddenPMRef.current?.isFocused()) focusHiddenEditor();
4914
5382
  }, [focusHiddenEditor]);
4915
5383
  useEffect(() => {
@@ -4975,19 +5443,19 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4975
5443
  /**
4976
5444
  * Run initial layout when document or view changes.
4977
5445
  */
4978
- const handleEditorViewReady = useCallback((view_20) => {
4979
- onEditorViewReadyRef.current?.(view_20);
4980
- anonymizationMatchesRef.current = anonymizationDecorationsKey.getState(view_20.state)?.matches ?? [];
4981
- const initialSuggestion = autocompleteSuggestionKey.getState(view_20.state)?.suggestion;
5446
+ const handleEditorViewReady = useCallback((view_21) => {
5447
+ onEditorViewReadyRef.current?.(view_21);
5448
+ anonymizationMatchesRef.current = anonymizationDecorationsKey.getState(view_21.state)?.matches ?? [];
5449
+ const initialSuggestion = autocompleteSuggestionKey.getState(view_21.state)?.suggestion;
4982
5450
  if (initialSuggestion !== void 0) autocompleteSuggestionRef.current = initialSuggestion;
4983
5451
  updateAutocompleteOverlay();
4984
- directivesRef.current = templateDirectivesKey.getState(view_20.state)?.ranges ?? [];
4985
- const previewState = templatePreviewValuesKey.getState(view_20.state);
5452
+ directivesRef.current = templateDirectivesKey.getState(view_21.state)?.ranges ?? [];
5453
+ const previewState = templatePreviewValuesKey.getState(view_21.state);
4986
5454
  templatePreviewRef.current = {
4987
5455
  entries: previewState?.entries ?? EMPTY_TEMPLATE_PREVIEW_ENTRIES,
4988
5456
  mode: previewState?.preview?.mode ?? "plain"
4989
5457
  };
4990
- const aiState = aiSuggestionDecorationsKey.getState(view_20.state);
5458
+ const aiState = aiSuggestionDecorationsKey.getState(view_21.state);
4991
5459
  aiSuggestionsRef.current = {
4992
5460
  suggestions: aiState?.suggestions ?? EMPTY_AI_SUGGESTIONS,
4993
5461
  focusedId: aiState?.focusedId ?? null
@@ -4995,16 +5463,16 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4995
5463
  const focusReadyView = () => {
4996
5464
  if (readOnly || !shouldFocusHiddenEditorOnReadyRef.current) return;
4997
5465
  requestAnimationFrame(() => {
4998
- if (hiddenPMRef.current?.getView() !== view_20) return;
4999
- applyPendingHiddenEditorInput(view_20);
5000
- view_20.focus();
5466
+ if (hiddenPMRef.current?.getView() !== view_21) return;
5467
+ applyPendingHiddenEditorInput(view_21);
5468
+ view_21.focus();
5001
5469
  setIsFocused(true);
5002
5470
  });
5003
5471
  };
5004
- if (layoutSessionRef.current.lastPmDoc?.eq(view_20.state.doc)) {
5472
+ if (layoutSessionRef.current.lastPmDoc?.eq(view_21.state.doc)) {
5005
5473
  const lastPreview = layoutSessionRef.current.lastTemplatePreview;
5006
- if (templatePreviewRef.current.mode !== lastPreview.mode || templatePreviewDirtyRange(lastPreview.entries, templatePreviewRef.current.entries) !== null) runLayoutPipeline$1(view_20.state, { reason: "manual" });
5007
- updateSelectionOverlay(view_20.state);
5474
+ if (templatePreviewRef.current.mode !== lastPreview.mode || templatePreviewDirtyRange(lastPreview.entries, templatePreviewRef.current.entries) !== null) runLayoutPipeline$1(view_21.state, { reason: "manual" });
5475
+ updateSelectionOverlay(view_21.state);
5008
5476
  updateAnonymizationOverlay();
5009
5477
  updateDirectivesOverlay();
5010
5478
  updateAISuggestionsOverlay();
@@ -5023,7 +5491,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5023
5491
  const runAfterFontWait_0 = (fontsLoaded_0) => {
5024
5492
  pendingInitialFontReadyLayoutRef.current = false;
5025
5493
  const currentView_0 = hiddenPMRef.current?.getView();
5026
- if (currentView_0 !== view_20) return;
5494
+ if (currentView_0 !== view_21) return;
5027
5495
  recordLayoutPhase("initial", "initial-fonts", performance.now() - fontWaitStartedAt_0);
5028
5496
  resetCanvasContext();
5029
5497
  clearAllCaches();
@@ -5033,7 +5501,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5033
5501
  suppressFontReadyUntilRef.current = performance.now() + INITIAL_FONT_READY_SUPPRESSION_MS;
5034
5502
  }
5035
5503
  };
5036
- waitForInitialLayoutFonts(document, view_20.state.doc).then(runAfterFontWait_0, () => runAfterFontWait_0(false));
5504
+ waitForInitialLayoutFonts(document, view_21.state.doc).then(runAfterFontWait_0, () => runAfterFontWait_0(false));
5037
5505
  focusReadyView();
5038
5506
  }, [
5039
5507
  applyPendingHiddenEditorInput,
@@ -5058,6 +5526,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5058
5526
  useEffect(() => {
5059
5527
  updateAISuggestionsOverlay();
5060
5528
  }, [updateAISuggestionsOverlay]);
5529
+ useEffect(() => {
5530
+ updatePassageHighlightOverlay();
5531
+ }, [updatePassageHighlightOverlay]);
5061
5532
  useEffect(() => {
5062
5533
  if (!onAnchorPositionsChange || !layout) return;
5063
5534
  let cancelled_0 = false;
@@ -5091,12 +5562,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5091
5562
  };
5092
5563
  const handleFontsLoaded = () => {
5093
5564
  if (pendingInitialFontReadyLayoutRef.current || performance.now() < suppressFontReadyUntilRef.current || layoutSessionRef.current.usedLoadedFonts) return;
5094
- const view_21 = hiddenPMRef.current?.getView();
5095
- if (view_21) {
5565
+ const view_22 = hiddenPMRef.current?.getView();
5566
+ if (view_22) {
5096
5567
  resetCanvasContext();
5097
5568
  clearAllCaches();
5098
- runLayoutPipelineRef.current(view_21.state, { reason: "font-ready" });
5099
- updateSelectionOverlayRef.current(view_21.state);
5569
+ runLayoutPipelineRef.current(view_22.state, { reason: "font-ready" });
5570
+ updateSelectionOverlayRef.current(view_22.state);
5100
5571
  }
5101
5572
  };
5102
5573
  fontSet.addEventListener("loading", handleFontsLoading);
@@ -5113,23 +5584,25 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5113
5584
  if (!embeddedFontBuffer) return;
5114
5585
  let cancelled_1 = false;
5115
5586
  let registered = [];
5116
- loadEmbeddedFontFaces(embeddedFontBuffer).then((faces) => {
5587
+ loadEmbeddedFontFaces(embeddedFontBuffer).then(({ faces, familyMap }) => {
5117
5588
  if (cancelled_1) {
5118
5589
  removeFontFaces(faces);
5119
5590
  return;
5120
5591
  }
5121
5592
  registered = faces;
5122
- if (faces.length === 0) return;
5123
- const view_22 = hiddenPMRef.current?.getView();
5124
- if (!view_22) return;
5593
+ if (faces.length === 0 && familyMap.size === 0) return;
5594
+ setEmbeddedFontFamilyMap(familyMap.size > 0 ? familyMap : null);
5595
+ const view_23 = hiddenPMRef.current?.getView();
5596
+ if (!view_23) return;
5125
5597
  resetCanvasContext();
5126
5598
  clearAllCaches();
5127
- runLayoutPipelineRef.current(view_22.state, { reason: "font-ready" });
5128
- updateSelectionOverlayRef.current(view_22.state);
5599
+ runLayoutPipelineRef.current(view_23.state, { reason: "font-ready" });
5600
+ updateSelectionOverlayRef.current(view_23.state);
5129
5601
  });
5130
5602
  return () => {
5131
5603
  cancelled_1 = true;
5132
5604
  removeFontFaces(registered);
5605
+ setEmbeddedFontFamilyMap(null);
5133
5606
  };
5134
5607
  }, [embeddedFontBuffer]);
5135
5608
  useEffect(() => {
@@ -5137,12 +5610,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5137
5610
  let cancelled_2 = false;
5138
5611
  let registered_0 = [];
5139
5612
  const remeasureForFontChange = () => {
5140
- const view_23 = hiddenPMRef.current?.getView();
5141
- if (!view_23) return;
5613
+ const view_24 = hiddenPMRef.current?.getView();
5614
+ if (!view_24) return;
5142
5615
  resetCanvasContext();
5143
5616
  clearAllCaches();
5144
- runLayoutPipelineRef.current(view_23.state, { reason: "font-ready" });
5145
- updateSelectionOverlayRef.current(view_23.state);
5617
+ runLayoutPipelineRef.current(view_24.state, { reason: "font-ready" });
5618
+ updateSelectionOverlayRef.current(view_24.state);
5146
5619
  };
5147
5620
  loadHostFontFaces(hostFonts).then((faces_0) => {
5148
5621
  if (cancelled_2) {
@@ -5168,12 +5641,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5168
5641
  lastLayoutInputSignatureRef.current = layoutInputSignature;
5169
5642
  return;
5170
5643
  }
5171
- const view_24 = hiddenPMRef.current?.getView();
5172
- if (view_24) {
5644
+ const view_25 = hiddenPMRef.current?.getView();
5645
+ if (view_25) {
5173
5646
  const layoutInputsChanged = lastLayoutInputSignatureRef.current !== layoutInputSignature;
5174
5647
  lastLayoutInputSignatureRef.current = layoutInputSignature;
5175
- if (!layoutInputsChanged && view_24.state.doc === layoutSessionRef.current.lastPmDoc) return;
5176
- runLayoutPipelineRef.current(view_24.state, { reason: "layout-input" });
5648
+ if (!layoutInputsChanged && view_25.state.doc === layoutSessionRef.current.lastPmDoc) return;
5649
+ runLayoutPipelineRef.current(view_25.state, { reason: "layout-input" });
5177
5650
  }
5178
5651
  }, [document, layoutInputSignature]);
5179
5652
  useEffect(() => {
@@ -5191,7 +5664,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5191
5664
  return folioEditor;
5192
5665
  },
5193
5666
  getDocument() {
5194
- return folioEditor.getDocument();
5667
+ const current_0 = folioEditor.getDocument();
5668
+ return current_0 ? noteEditorRef.current?.snapshotDocument(current_0) ?? current_0 : null;
5195
5669
  },
5196
5670
  getState() {
5197
5671
  return folioEditor.getState();
@@ -5199,6 +5673,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5199
5673
  getView() {
5200
5674
  return folioEditor.getView();
5201
5675
  },
5676
+ getActiveView() {
5677
+ return getActiveEditorStory().view;
5678
+ },
5679
+ closeNoteStory() {
5680
+ noteEditorRef.current?.close();
5681
+ },
5202
5682
  getHfView(rId_0) {
5203
5683
  return hfPMsRef.current?.getView(rId_0) ?? null;
5204
5684
  },
@@ -5206,30 +5686,37 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5206
5686
  ensureHiddenEditorView(options_4);
5207
5687
  },
5208
5688
  focus() {
5209
- folioEditor.focus();
5689
+ getActiveEditorStory().view?.focus();
5210
5690
  setIsFocused(true);
5211
5691
  },
5212
5692
  blur() {
5213
- folioEditor.blur();
5693
+ const view_26 = getActiveEditorStory().view;
5694
+ if (view_26?.hasFocus() && view_26.dom instanceof HTMLElement) view_26.dom.blur();
5214
5695
  setIsFocused(false);
5215
5696
  },
5216
5697
  isFocused() {
5217
- return folioEditor.isFocused();
5698
+ return getActiveEditorStory().view?.hasFocus() ?? false;
5218
5699
  },
5219
5700
  dispatch(tr_6) {
5220
5701
  folioEditor.dispatch(tr_6);
5221
5702
  },
5222
5703
  undo() {
5223
- return folioEditor.undo();
5704
+ const target_4 = getActiveEditorStory();
5705
+ if (target_4.type === "none") return false;
5706
+ return undo(target_4.view.state, target_4.view.dispatch);
5224
5707
  },
5225
5708
  redo() {
5226
- return folioEditor.redo();
5709
+ const target_5 = getActiveEditorStory();
5710
+ if (target_5.type === "none") return false;
5711
+ return redo(target_5.view.state, target_5.view.dispatch);
5227
5712
  },
5228
5713
  canUndo() {
5229
- return folioEditor.canUndo();
5714
+ const target_6 = getActiveEditorStory();
5715
+ return target_6.type === "none" ? false : undo(target_6.view.state);
5230
5716
  },
5231
5717
  canRedo() {
5232
- return folioEditor.canRedo();
5718
+ const target_7 = getActiveEditorStory();
5719
+ return target_7.type === "none" ? false : redo(target_7.view.state);
5233
5720
  },
5234
5721
  setSelection(anchor_3, head_1) {
5235
5722
  folioEditor.setSelection(anchor_3, head_1);
@@ -5243,6 +5730,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5243
5730
  scrollToPosition: scrollToPositionImpl,
5244
5731
  scrollToPage: scrollToPageImpl,
5245
5732
  scrollToParaId: scrollToParaIdImpl,
5733
+ setPassageHighlight: setPassageHighlightImpl,
5246
5734
  getPageNumberForPmPos(pmPos_18) {
5247
5735
  const container_0 = pagesContainerRef.current;
5248
5736
  if (!container_0) return null;
@@ -5281,9 +5769,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5281
5769
  }), [
5282
5770
  ensureHiddenEditorView,
5283
5771
  folioEditor,
5772
+ getActiveEditorStory,
5284
5773
  scrollToPageImpl,
5285
5774
  scrollToParaIdImpl,
5286
- scrollToPositionImpl
5775
+ scrollToPositionImpl,
5776
+ setPassageHighlightImpl
5287
5777
  ]);
5288
5778
  useEffect(() => {
5289
5779
  if (!layout) return;
@@ -5350,6 +5840,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5350
5840
  ...styles !== void 0 ? { styles } : {},
5351
5841
  ..._theme !== void 0 ? { theme: _theme } : {}
5352
5842
  }),
5843
+ /* @__PURE__ */ jsx(NoteStoryEditor, {
5844
+ ref: noteEditorRef,
5845
+ document,
5846
+ onActiveChange: handleActiveNoteStoryChange,
5847
+ onDocumentChange: handleNoteDocumentChange,
5848
+ onStoryChange: handleNoteStoryTransaction,
5849
+ plugins: noteStoryPlugins,
5850
+ suggestionModeActive,
5851
+ ...suggestionAuthor !== void 0 ? { suggestionAuthor } : {},
5852
+ ...styles !== void 0 ? { styles } : {},
5853
+ ..._theme !== void 0 ? { theme: _theme } : {}
5854
+ }),
5353
5855
  /* @__PURE__ */ jsx(HiddenProseMirror, {
5354
5856
  ref: hiddenPMRef,
5355
5857
  document,
@@ -5363,6 +5865,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5363
5865
  onEditorViewReady: handleEditorViewReady,
5364
5866
  onEditorViewDestroy: handleEditorViewDestroy,
5365
5867
  onKeyDown: handleHiddenEditorKeyDown,
5868
+ ...onCopy !== void 0 ? { onCopy } : {},
5869
+ ...onCut !== void 0 ? { onCut } : {},
5870
+ ...onPaste !== void 0 ? { onPaste } : {},
5366
5871
  ...styles !== void 0 ? { styles } : {},
5367
5872
  externalPlugins,
5368
5873
  ...collaboration !== void 0 ? { collaboration } : {},
@@ -5392,6 +5897,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5392
5897
  selectedCanonical: selectedAnonymizationCanonical,
5393
5898
  selectionSeq: anonymizationSelectionSeq
5394
5899
  }),
5900
+ /* @__PURE__ */ jsx(PassageHighlightOverlay, { rects: passageHighlightRects }),
5395
5901
  /* @__PURE__ */ jsx(AutocompleteCaretOverlay, {
5396
5902
  caret: autocompleteCaret,
5397
5903
  text: autocompleteText,
@@ -5405,8 +5911,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5405
5911
  ranges: directivesRef.current
5406
5912
  }),
5407
5913
  /* @__PURE__ */ jsx(SelectionOverlay, {
5408
- selectionRects: hfEditMode ? EMPTY_SELECTION_RECTS : selectionRects,
5409
- caretPosition: hfEditMode ? null : caretPosition,
5914
+ selectionRects: hfEditMode || noteStoryActive ? EMPTY_SELECTION_RECTS : selectionRects,
5915
+ caretPosition: hfEditMode || noteStoryActive ? null : caretPosition,
5410
5916
  isFocused,
5411
5917
  pageGap,
5412
5918
  markCaretRect: true
@@ -6689,133 +7195,145 @@ function removePendingCommentMarkRange(view, range) {
6689
7195
  }
6690
7196
  //#endregion
6691
7197
  //#region src/components/ContentControlWidgetsOverlay.tsx
6692
- /**
6693
- * React shell for the content-control widgets plugin.
6694
- *
6695
- * The plugin (see `core/prosemirror/plugins/contentControlWidgets`) emits a
6696
- * `folio:content-control-widget` CustomEvent on the editor's view DOM
6697
- * whenever the user clicks a typed control. This component subscribes to
6698
- * those events and renders a small floating picker positioned at the
6699
- * anchor element — a list of menu items for dropdown / comboBox
6700
- * controls, a shared date picker for date controls — then dispatches back
6701
- * through `dispatchDropdownPick` / `dispatchDatePick` so the change rides
6702
- * the normal undo stack.
6703
- *
6704
- * The dropdown popover uses the injected `MenuItem` for visual + a11y
6705
- * consistency with the rest of the editor.
6706
- */
6707
- function parseListItems(raw) {
6708
- if (!raw) return [];
6709
- try {
6710
- const parsed = JSON.parse(raw);
6711
- if (!Array.isArray(parsed)) return [];
6712
- const out = [];
6713
- for (const entry of parsed) if (entry !== null && typeof entry === "object" && "displayText" in entry && "value" in entry && typeof entry.displayText === "string" && typeof entry.value === "string") out.push(entry);
6714
- return out;
6715
- } catch {
6716
- return [];
6717
- }
6718
- }
6719
- function ContentControlWidgetsOverlay({ getEditorView }) {
7198
+ /** Thin React renderer for the shared content-control widget controller. */
7199
+ function ContentControlWidgetsOverlay(t0) {
7200
+ const $ = c(32);
7201
+ const { getEventRoot, getEditorView } = t0;
6720
7202
  const folioUI = useFolioUI();
6721
- const { Item: MenuItem } = folioUI.Menu;
7203
+ const { Root: Menu, Item: MenuItem } = folioUI.Menu;
6722
7204
  const DatePickerPopover = folioUI.DatePickerPopover;
6723
7205
  const t = useTranslations("folio");
6724
- const [open, setOpen] = useState(null);
6725
- const getEditorViewRef = useRef(getEditorView);
6726
- getEditorViewRef.current = getEditorView;
6727
- const close = useCallback(() => setOpen(null), []);
6728
- const viewDom = getEditorView()?.dom ?? null;
6729
- useEffect(() => {
6730
- if (!viewDom) return;
6731
- const onWidget = (event) => {
6732
- const detail = event.detail;
6733
- if (detail.kind === "dropdownOpen") {
6734
- const items = parseListItems(detail.listItemsJson);
6735
- setOpen({
6736
- kind: "dropdown",
6737
- pmPos: detail.pmPos,
6738
- items,
6739
- anchorRect: detail.anchor.getBoundingClientRect()
6740
- });
6741
- return;
6742
- }
6743
- if (detail.kind === "datePick") setOpen({
6744
- kind: "date",
6745
- pmPos: detail.pmPos,
6746
- anchorRect: detail.anchor.getBoundingClientRect()
6747
- });
6748
- };
6749
- viewDom.addEventListener(CONTENT_CONTROL_WIDGET_EVENT_NAME, onWidget);
6750
- return () => {
6751
- viewDom.removeEventListener(CONTENT_CONTROL_WIDGET_EVENT_NAME, onWidget);
6752
- };
6753
- }, [viewDom]);
6754
- useEffect(() => {
6755
- if (!open) return;
6756
- const onKey = (event_0) => {
6757
- if (event_0.key === "Escape") close();
6758
- };
6759
- const onScroll = () => close();
6760
- window.addEventListener("keydown", onKey);
6761
- window.addEventListener("scroll", onScroll, true);
6762
- return () => {
6763
- window.removeEventListener("keydown", onKey);
6764
- window.removeEventListener("scroll", onScroll, true);
7206
+ let t1;
7207
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
7208
+ t1 = new ContentControlWidgetController();
7209
+ $[0] = t1;
7210
+ } else t1 = $[0];
7211
+ const controller = t1;
7212
+ const snapshot = useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
7213
+ let t2;
7214
+ if ($[1] !== getEditorView) {
7215
+ t2 = getEditorView();
7216
+ $[1] = getEditorView;
7217
+ $[2] = t2;
7218
+ } else t2 = $[2];
7219
+ const view = t2;
7220
+ let t3;
7221
+ let t4;
7222
+ if ($[3] !== getEventRoot || $[4] !== view) {
7223
+ t3 = () => {
7224
+ controller.bind(view, getEventRoot());
7225
+ return () => controller.destroy();
6765
7226
  };
6766
- }, [open, close]);
6767
- const style = useMemo(() => {
6768
- if (!open) return;
6769
- return {
7227
+ t4 = [
7228
+ controller,
7229
+ getEventRoot,
7230
+ view
7231
+ ];
7232
+ $[3] = getEventRoot;
7233
+ $[4] = view;
7234
+ $[5] = t3;
7235
+ $[6] = t4;
7236
+ } else {
7237
+ t3 = $[5];
7238
+ t4 = $[6];
7239
+ }
7240
+ useEffect(t3, t4);
7241
+ let t5;
7242
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
7243
+ t5 = (value) => controller.pickDropdown(value);
7244
+ $[7] = t5;
7245
+ } else t5 = $[7];
7246
+ const onDropdownPick = t5;
7247
+ let t6;
7248
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
7249
+ t6 = (value_0) => value_0 ? controller.pickDate(value_0) : false;
7250
+ $[8] = t6;
7251
+ } else t6 = $[8];
7252
+ const onDateChange = t6;
7253
+ if (snapshot.status === "closed") return null;
7254
+ const t7 = `${snapshot.position.y}px`;
7255
+ const t8 = `${snapshot.position.x}px`;
7256
+ let t9;
7257
+ if ($[9] !== t7 || $[10] !== t8) {
7258
+ t9 = {
6770
7259
  position: "fixed",
6771
- top: `${open.anchorRect.bottom + 4}px`,
6772
- insetInlineStart: `${open.anchorRect.left}px`,
7260
+ top: t7,
7261
+ insetInlineStart: t8,
6773
7262
  zIndex: 9999
6774
7263
  };
6775
- }, [open]);
6776
- const openPmPos = open?.pmPos;
6777
- const onDropdownPick = useCallback((value) => {
6778
- const liveView = getEditorViewRef.current();
6779
- if (liveView && typeof openPmPos === "number") dispatchDropdownPick(liveView, openPmPos, value);
6780
- close();
6781
- }, [close, openPmPos]);
6782
- const onDatePick = useCallback((value_0) => {
6783
- const liveView_0 = getEditorViewRef.current();
6784
- if (liveView_0 && value_0.length > 0 && typeof openPmPos === "number") dispatchDatePick(liveView_0, openPmPos, value_0);
6785
- close();
6786
- }, [close, openPmPos]);
6787
- const handleDateChange = useCallback((value_1) => {
6788
- if (value_1) onDatePick(value_1);
6789
- }, [onDatePick]);
6790
- if (!open) return null;
6791
- return createPortal(/* @__PURE__ */ jsx("div", {
6792
- className: "folio-root",
6793
- style: { display: "contents" },
6794
- children: /* @__PURE__ */ jsxs("div", {
6795
- role: "dialog",
6796
- "aria-label": open.kind === "dropdown" ? t("contentControlDropdownAriaLabel") : t("contentControlDateAriaLabel"),
6797
- style,
6798
- className: "bg-popover text-popover-foreground min-w-[10rem] rounded-md border p-1 shadow-md",
6799
- children: [open.kind === "dropdown" && /* @__PURE__ */ jsx("div", {
6800
- role: "menu",
6801
- className: "flex flex-col",
6802
- children: open.items.length === 0 ? /* @__PURE__ */ jsx("div", {
6803
- className: "text-muted-foreground px-2 py-1 text-sm",
6804
- children: t("contentControlDropdownNoOptions")
6805
- }) : open.items.map((item) => /* @__PURE__ */ jsx(ContentControlDropdownItem, {
6806
- item,
6807
- MenuItem,
6808
- onPick: onDropdownPick
6809
- }, `${item.value}::${item.displayText}`))
6810
- }), open.kind === "date" && /* @__PURE__ */ jsx(DatePickerPopover, {
6811
- clearLabel: t("clearDate"),
6812
- defaultOpen: true,
6813
- onChange: handleDateChange,
6814
- showIcon: false,
6815
- value: null
6816
- })]
6817
- })
6818
- }), document.body);
7264
+ $[9] = t7;
7265
+ $[10] = t8;
7266
+ $[11] = t9;
7267
+ } else t9 = $[11];
7268
+ const style = t9;
7269
+ let t10;
7270
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
7271
+ t10 = { display: "contents" };
7272
+ $[12] = t10;
7273
+ } else t10 = $[12];
7274
+ let t11;
7275
+ if ($[13] !== snapshot.status || $[14] !== t) {
7276
+ t11 = snapshot.status === "dropdown" ? t("contentControlDropdownAriaLabel") : t("contentControlDateAriaLabel");
7277
+ $[13] = snapshot.status;
7278
+ $[14] = t;
7279
+ $[15] = t11;
7280
+ } else t11 = $[15];
7281
+ let t12;
7282
+ if ($[16] !== Menu || $[17] !== MenuItem || $[18] !== snapshot.items || $[19] !== snapshot.status || $[20] !== t) {
7283
+ t12 = snapshot.status === "dropdown" && /* @__PURE__ */ jsx(Menu, { children: /* @__PURE__ */ jsx("div", {
7284
+ role: "menu",
7285
+ className: "flex flex-col",
7286
+ children: snapshot.items.length === 0 ? /* @__PURE__ */ jsx("div", {
7287
+ className: "text-muted-foreground px-2 py-1 text-sm",
7288
+ children: t("contentControlDropdownNoOptions")
7289
+ }) : snapshot.items.map((item) => /* @__PURE__ */ jsx(ContentControlDropdownItem, {
7290
+ item,
7291
+ MenuItem,
7292
+ onPick: onDropdownPick
7293
+ }, `${item.value}::${item.displayText}`))
7294
+ }) });
7295
+ $[16] = Menu;
7296
+ $[17] = MenuItem;
7297
+ $[18] = snapshot.items;
7298
+ $[19] = snapshot.status;
7299
+ $[20] = t;
7300
+ $[21] = t12;
7301
+ } else t12 = $[21];
7302
+ let t13;
7303
+ if ($[22] !== DatePickerPopover || $[23] !== snapshot.currentValue || $[24] !== snapshot.status || $[25] !== t) {
7304
+ t13 = snapshot.status === "date" && /* @__PURE__ */ jsx(DatePickerPopover, {
7305
+ clearLabel: t("clearDate"),
7306
+ defaultOpen: true,
7307
+ onChange: onDateChange,
7308
+ showIcon: false,
7309
+ value: snapshot.currentValue
7310
+ });
7311
+ $[22] = DatePickerPopover;
7312
+ $[23] = snapshot.currentValue;
7313
+ $[24] = snapshot.status;
7314
+ $[25] = t;
7315
+ $[26] = t13;
7316
+ } else t13 = $[26];
7317
+ let t14;
7318
+ if ($[27] !== style || $[28] !== t11 || $[29] !== t12 || $[30] !== t13) {
7319
+ t14 = createPortal(/* @__PURE__ */ jsx("div", {
7320
+ className: "folio-root",
7321
+ style: t10,
7322
+ children: /* @__PURE__ */ jsxs("div", {
7323
+ role: "dialog",
7324
+ "aria-label": t11,
7325
+ style,
7326
+ className: "bg-popover text-popover-foreground min-w-[10rem] rounded-md border p-1 shadow-md",
7327
+ children: [t12, t13]
7328
+ })
7329
+ }), document.body);
7330
+ $[27] = style;
7331
+ $[28] = t11;
7332
+ $[29] = t12;
7333
+ $[30] = t13;
7334
+ $[31] = t14;
7335
+ } else t14 = $[31];
7336
+ return t14;
6819
7337
  }
6820
7338
  function ContentControlDropdownItem(t0) {
6821
7339
  const $ = c(7);
@@ -11682,13 +12200,52 @@ const getBuiltinTableStyle = (styleId) => BUILTIN_STYLES.find((s) => s.id === st
11682
12200
  * (`replaceComments`/`updateComments`) stay in the component because they
11683
12201
  * depend on its document-build pipeline.
11684
12202
  */
12203
+ /**
12204
+ * Sanitize a `paraId`/`textId`-bearing paragraph: drop either field when it
12205
+ * isn't a well-formed OOXML long-hex id (see `isValidHexId`), leaving
12206
+ * everything else untouched. Comment paragraphs from a controlled
12207
+ * `commentsProp` come from the host app rather than our own parser/
12208
+ * serializer, so they aren't guaranteed to satisfy the id shape those trust.
12209
+ */
12210
+ function sanitizeCommentParagraph(paragraph) {
12211
+ const paraIdValid = paragraph.paraId === void 0 || isValidHexId(paragraph.paraId);
12212
+ const textIdValid = paragraph.textId === void 0 || isValidHexId(paragraph.textId);
12213
+ if (paraIdValid && textIdValid) return paragraph;
12214
+ const { paraId, textId, ...rest } = paragraph;
12215
+ return {
12216
+ ...rest,
12217
+ ...paraIdValid && paraId !== void 0 ? { paraId } : {},
12218
+ ...textIdValid && textId !== void 0 ? { textId } : {}
12219
+ };
12220
+ }
12221
+ /**
12222
+ * Validate a controlled `commentsProp` at the boundary before it becomes
12223
+ * editor state. A host app (or a collaboration payload relayed through it)
12224
+ * can hand back arbitrary JSON, so `id` isn't guaranteed numeric and
12225
+ * paragraph `paraId`/`textId` aren't guaranteed to be real Word ids — both
12226
+ * eventually reach XML/CSS-adjacent serialization (comment threading,
12227
+ * `[data-comment-id]` selectors). Comments with a non-finite `id` are
12228
+ * dropped entirely; malformed paraId/textId are stripped in place.
12229
+ */
12230
+ function sanitizeControlledComments(comments) {
12231
+ const sanitized = [];
12232
+ for (const comment of comments) {
12233
+ if (!Number.isFinite(comment.id)) continue;
12234
+ sanitized.push({
12235
+ ...comment,
12236
+ content: comment.content.map(sanitizeCommentParagraph)
12237
+ });
12238
+ }
12239
+ return sanitized;
12240
+ }
11685
12241
  function useFolioComments({ doc, autoOpenReviewSidebar, anchorPositions, editorContentRef, commentsProp, onCommentsChange }) {
11686
12242
  const [showCommentsSidebar, setShowCommentsSidebar] = useState(false);
11687
12243
  const [visibleCommentAuthors, setVisibleCommentAuthors] = useState(null);
11688
12244
  const [activeCommentId, setActiveCommentId] = useState(null);
11689
12245
  const [internalComments, setInternalComments] = useState([]);
11690
- const isControlledComments = commentsProp !== void 0;
11691
- const comments = isControlledComments ? commentsProp : internalComments;
12246
+ const sanitizedCommentsProp = useMemo(() => commentsProp !== void 0 ? sanitizeControlledComments(commentsProp) : void 0, [commentsProp]);
12247
+ const isControlledComments = sanitizedCommentsProp !== void 0;
12248
+ const comments = isControlledComments ? sanitizedCommentsProp : internalComments;
11692
12249
  const commentsDirtyRef = useRef(false);
11693
12250
  const commentsRef = useRef(comments);
11694
12251
  commentsRef.current = comments;
@@ -11843,7 +12400,7 @@ function useFolioComments({ doc, autoOpenReviewSidebar, anchorPositions, editorC
11843
12400
  * - Error boundary
11844
12401
  * - Loading states
11845
12402
  */
11846
- const CommentsSidebar = lazy(() => import("./CommentsSidebar-DOSa22AJ.js").then((m) => ({ default: m.CommentsSidebar })));
12403
+ const CommentsSidebar = lazy(() => import("./CommentsSidebar-mwa9JsIj.js").then((m) => ({ default: m.CommentsSidebar })));
11847
12404
  const TextContextMenu = lazy(() => import("./TextContextMenu-Ci7-M4oU.js").then((m) => ({ default: m.TextContextMenu })));
11848
12405
  const loadAttemptSelectiveSave = async () => {
11849
12406
  const { attemptSelectiveSave } = await import("@stll/folio-core/docx/selectiveSave");
@@ -11905,7 +12462,7 @@ function areActiveTrackedChangesEqual(a, b) {
11905
12462
  /**
11906
12463
  * DocxEditor - Complete DOCX editor component
11907
12464
  */
11908
- const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, document: initialDocument, documentKey, onSave, author = "User", onChange, onSelectionChange, onSelectionTextChange, onError, onFontsLoaded: onFontsLoadedCallback, fontFamilies, fonts, theme, showToolbar = true, showZoomControl = true, showReviewControls = true, showHeaderFooterEditing = true, showMarginGuides: _showMarginGuides = false, marginGuideColor: _marginGuideColor, showRuler: showRulerProp = false, rulerUnit = "inch", initialZoom = 1, enableWheelZoom = true, readOnly: readOnlyProp = false, autoOpenReviewSidebar = true, components, toolbarExtra, className = "", style, placeholder, loadingIndicator, preserveDocumentWhileLoading = false, initialScrollTop, onScrollTopChange, showOutline: showOutlineProp = true, onPrint, onInsertImage, onInsertTable, showTableInsert = true, onInsertPageBreak, onInsertTOC, onCopy: _onCopy, onCut: _onCut, onPaste: _onPaste, mode: modeProp, onModeChange, onReadonlyEditAttempt, onCompatibilityChange, onEditorViewReady, onAnonymizationMatchesChange, onAnonymizationTermClick, selectedAnonymizationCanonical = null, anonymizationSelectionSeq, showTemplateDirectives = false, onSlashMenuChange, onSlashMenuKeyAction, customContextMenuItems, onCustomContextAction, comments: commentsProp, onCommentsChange, collaboration, featureFlags, onSelectiveSaveTripwire }, ref) {
12465
+ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, document: initialDocument, documentKey, onSave, author = "User", onChange, onSelectionChange, onSelectionTextChange, onError, onFontsLoaded: onFontsLoadedCallback, fontFamilies, fonts, theme, showToolbar = true, showZoomControl = true, showReviewControls = true, showHeaderFooterEditing = true, showMarginGuides = false, marginGuideColor, showRuler: showRulerProp = false, rulerUnit = "inch", initialZoom = 1, enableWheelZoom = true, readOnly: readOnlyProp = false, autoOpenReviewSidebar = true, components, toolbarExtra, className = "", style, placeholder, loadingIndicator, preserveDocumentWhileLoading = false, initialScrollTop, onScrollTopChange, showOutline: showOutlineProp = true, onPrint, onInsertImage, onInsertTable, showTableInsert = true, onInsertPageBreak, onInsertTOC, onCopy, onCut, onPaste, mode: modeProp, onModeChange, onReadonlyEditAttempt, onCompatibilityChange, onEditorViewReady, onAnonymizationMatchesChange, onAnonymizationTermClick, selectedAnonymizationCanonical = null, anonymizationSelectionSeq, showTemplateDirectives = false, onSlashMenuChange, onSlashMenuKeyAction, customContextMenuItems, onCustomContextAction, comments: commentsProp, onCommentsChange, collaboration, featureFlags, onSelectiveSaveTripwire }, ref) {
11909
12466
  const t = useTranslations("folio");
11910
12467
  useEffect(() => {
11911
12468
  const onClipboardReadError = () => {
@@ -11941,6 +12498,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
11941
12498
  showOutlineRef.current = showOutline;
11942
12499
  const [outlineHeadings, setHeadingInfos] = useState([]);
11943
12500
  const [, setTrackedChanges] = useState([]);
12501
+ const trackedChangesRef = useRef([]);
11944
12502
  const [anchorPositions, setAnchorPositions] = useState(EMPTY_ANCHOR_POSITIONS);
11945
12503
  const { editingMode, readOnly, trackChangesOn, toggleTrackChanges, displayMode, setDisplayMode } = useEditorMode({
11946
12504
  modeProp,
@@ -11980,6 +12538,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
11980
12538
  last.to = entry_0.to;
11981
12539
  } else merged.push({ ...entry_0 });
11982
12540
  }
12541
+ trackedChangesRef.current = merged;
11983
12542
  setTrackedChanges(merged);
11984
12543
  }, []);
11985
12544
  useEffect(() => () => {
@@ -12153,6 +12712,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12153
12712
  canRedo: false,
12154
12713
  canUndo: false
12155
12714
  });
12715
+ const [activeNoteStory, setActiveNoteStory] = useState(null);
12156
12716
  const toolbarRefCallback = useCallback((el) => {
12157
12717
  toolbarWrapperRef.current = el;
12158
12718
  if (toolbarRoRef.current) {
@@ -12190,28 +12750,42 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12190
12750
  pushDocument,
12191
12751
  getHfView: (rId) => pagedEditorRef.current?.getHfView(rId) ?? null
12192
12752
  });
12193
- const getActiveEditorView = useCallback(() => {
12194
- if (hfEditPosition && hfEditorRef.current) return hfEditorRef.current.getView();
12195
- return pagedEditorRef.current?.getView();
12196
- }, [hfEditPosition]);
12753
+ let activeHfRId = hfEditIsFirstPage ? activeFirstFooterRId : activeFooterRId;
12754
+ if (hfEditPosition === "header") activeHfRId = hfEditIsFirstPage ? activeFirstHeaderRId : activeHeaderRId;
12755
+ const getActiveEditorStory = useCallback(() => {
12756
+ return resolveActiveEditorStory({
12757
+ bodyView: pagedEditorRef.current?.getView() ?? null,
12758
+ headerFooterView: hfEditPosition && hfEditorRef.current ? hfEditorRef.current.getView() : null,
12759
+ noteView: activeNoteStory ? pagedEditorRef.current?.getActiveView() ?? null : null
12760
+ });
12761
+ }, [activeNoteStory, hfEditPosition]);
12762
+ const getActiveEditorView = useCallback(() => getActiveEditorStory().view, [getActiveEditorStory]);
12197
12763
  const focusActiveEditor = useCallback(() => {
12198
- if (hfEditPosition && hfEditorRef.current) hfEditorRef.current.focus();
12764
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) hfEditorRef.current.focus();
12199
12765
  else pagedEditorRef.current?.focus();
12200
- }, [hfEditPosition]);
12766
+ }, [getActiveEditorStory]);
12201
12767
  const undoActiveEditor = useCallback(() => {
12202
- if (hfEditPosition && hfEditorRef.current) hfEditorRef.current.undo();
12768
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) hfEditorRef.current.undo();
12203
12769
  else {
12204
12770
  pagedEditorRef.current?.undo();
12205
12771
  requestAnimationFrame(refreshBodyHistoryAvailability);
12206
12772
  }
12207
- }, [hfEditPosition, refreshBodyHistoryAvailability]);
12773
+ }, [getActiveEditorStory, refreshBodyHistoryAvailability]);
12208
12774
  const redoActiveEditor = useCallback(() => {
12209
- if (hfEditPosition && hfEditorRef.current) hfEditorRef.current.redo();
12775
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) hfEditorRef.current.redo();
12210
12776
  else {
12211
12777
  pagedEditorRef.current?.redo();
12212
12778
  requestAnimationFrame(refreshBodyHistoryAvailability);
12213
12779
  }
12214
- }, [hfEditPosition, refreshBodyHistoryAvailability]);
12780
+ }, [getActiveEditorStory, refreshBodyHistoryAvailability]);
12781
+ const handleActiveNoteStoryChange = useCallback((story) => {
12782
+ setActiveNoteStory(story);
12783
+ if (story && hfEditPosition) handleBodyClick();
12784
+ }, [handleBodyClick, hfEditPosition]);
12785
+ const handleHeaderFooterStoryOpen = useCallback((position, pageNumber) => {
12786
+ pagedEditorRef.current?.closeNoteStory();
12787
+ handleHeaderFooterDoubleClick(position, pageNumber);
12788
+ }, [handleHeaderFooterDoubleClick]);
12215
12789
  const findReplace = useFindReplace$1();
12216
12790
  const [showPageSetup, setShowPageSetup] = useState(false);
12217
12791
  const { hyperlinkPopupData, handleHyperlinkClick, handleHyperlinkPopupNavigate, handleHyperlinkPopupCopy, handleHyperlinkPopupEdit, handleHyperlinkPopupRemove, handleHyperlinkPopupClose } = useHyperlinkHandlers({
@@ -12358,8 +12932,11 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12358
12932
  if (!history.state) return null;
12359
12933
  let doc_0 = structuredClone(history.state);
12360
12934
  const pmDoc = pagedEditorRef.current?.getDocument();
12361
- if (pmDoc) doc_0.package.document.content = pmDoc.package.document.content;
12362
- else doc_0 = normalizeBaseDirection(doc_0);
12935
+ if (pmDoc) {
12936
+ doc_0.package.document.content = pmDoc.package.document.content;
12937
+ if (pmDoc.package.footnotes !== void 0) doc_0.package.footnotes = pmDoc.package.footnotes;
12938
+ if (pmDoc.package.endnotes !== void 0) doc_0.package.endnotes = pmDoc.package.endnotes;
12939
+ } else doc_0 = normalizeBaseDirection(doc_0);
12363
12940
  const editor = pagedEditorRef.current;
12364
12941
  if (editor) {
12365
12942
  const flushBag = (bag) => {
@@ -13134,14 +13711,16 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13134
13711
  if (readOnly) return;
13135
13712
  const { from: from_7, to: to_7 } = view_12.state.selection;
13136
13713
  const text_2 = view_12.state.doc.textBetween(from_7, to_7, "\n");
13137
- navigator.clipboard.writeText(text_2);
13714
+ navigator.clipboard.writeText(text_2).catch(() => void 0);
13138
13715
  view_12.dispatch(view_12.state.tr.deleteSelection());
13716
+ onCut?.();
13139
13717
  break;
13140
13718
  }
13141
13719
  case "copy": {
13142
13720
  const { from: cf, to: ct } = view_12.state.selection;
13143
13721
  const copied = view_12.state.doc.textBetween(cf, ct, "\n");
13144
- navigator.clipboard.writeText(copied);
13722
+ navigator.clipboard.writeText(copied).catch(() => void 0);
13723
+ onCopy?.();
13145
13724
  break;
13146
13725
  }
13147
13726
  case "paste":
@@ -13166,7 +13745,10 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13166
13745
  } catch {
13167
13746
  try {
13168
13747
  const text_0 = await navigator.clipboard.readText();
13169
- if (text_0) view_12.dispatch(view_12.state.tr.insertText(text_0));
13748
+ if (text_0) {
13749
+ view_12.dispatch(view_12.state.tr.insertText(text_0));
13750
+ onPaste?.();
13751
+ }
13170
13752
  } catch {}
13171
13753
  }
13172
13754
  break;
@@ -13176,6 +13758,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13176
13758
  if (text && !view_12.isDestroyed) {
13177
13759
  const slice = buildPlainTextSlice(text, view_12.state.schema);
13178
13760
  view_12.dispatch(view_12.state.tr.replaceSelection(slice).scrollIntoView());
13761
+ onPaste?.();
13179
13762
  }
13180
13763
  } catch {
13181
13764
  toast(t("clipboardReadFailed"));
@@ -13249,6 +13832,9 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13249
13832
  getActiveEditorView,
13250
13833
  focusActiveEditor,
13251
13834
  onCustomContextAction,
13835
+ onCopy,
13836
+ onCut,
13837
+ onPaste,
13252
13838
  readOnly,
13253
13839
  contextMenu.selectionRange.from,
13254
13840
  contextMenu.selectionRange.to,
@@ -13385,8 +13971,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13385
13971
  },
13386
13972
  getCurrentPage: () => scrollPageInfo.currentPage,
13387
13973
  getTotalPages: () => scrollPageInfo.totalPages,
13388
- scrollToPage: (pageNumber) => {
13389
- pagedEditorRef.current?.scrollToPage(pageNumber);
13974
+ scrollToPage: (pageNumber_0) => {
13975
+ pagedEditorRef.current?.scrollToPage(pageNumber_0);
13390
13976
  },
13391
13977
  scrollToParaId: (paraId, options_0) => pagedEditorRef.current?.scrollToParaId(paraId, options_0) ?? false,
13392
13978
  openPrintPreview: handleDirectPrint,
@@ -13481,7 +14067,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13481
14067
  undoHandle,
13482
14068
  reason: "documentChanged"
13483
14069
  };
13484
- if (!(pagedEditorRef.current?.undo() ?? false)) return {
14070
+ if (!undo(view_21.state, view_21.dispatch)) return {
13485
14071
  status: "rejected",
13486
14072
  undoHandle,
13487
14073
  reason: "documentChanged"
@@ -13536,13 +14122,13 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13536
14122
  return rejectAIEditRevision(revisionId_0)(view_24.state, view_24.dispatch);
13537
14123
  },
13538
14124
  undo: () => {
13539
- if (hfEditPosition && hfEditorRef.current) return hfEditorRef.current.undo();
14125
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) return hfEditorRef.current.undo();
13540
14126
  const undone = pagedEditorRef.current?.undo() ?? false;
13541
14127
  requestAnimationFrame(refreshBodyHistoryAvailability);
13542
14128
  return undone;
13543
14129
  },
13544
14130
  redo: () => {
13545
- if (hfEditPosition && hfEditorRef.current) return hfEditorRef.current.redo();
14131
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) return hfEditorRef.current.redo();
13546
14132
  const redone = pagedEditorRef.current?.redo() ?? false;
13547
14133
  requestAnimationFrame(refreshBodyHistoryAvailability);
13548
14134
  return redone;
@@ -13579,104 +14165,177 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13579
14165
  });
13580
14166
  return true;
13581
14167
  },
13582
- showInDocument: (target_1, snapshot_2) => {
14168
+ highlightPassage: ({ blockId: blockId_0, text: text_5, snapshot: snapshot_2 }) => {
13583
14169
  const view_27 = pagedEditorRef.current?.getView();
13584
- if (!view_27) return false;
13585
- const range_4 = target_1.type === "textRange" ? resolveFolioAITextRange({
13586
- range: target_1,
14170
+ if (!view_27) return "none";
14171
+ const passageRange = resolvePassageRange({
14172
+ blockId: blockId_0,
14173
+ text: text_5,
13587
14174
  doc: view_27.state.doc,
13588
14175
  snapshot: snapshot_2
13589
- }) : resolveFolioAIBlockRange({
13590
- blockId: target_1.blockId,
14176
+ });
14177
+ if (passageRange !== null) {
14178
+ pagedEditorRef.current?.setPassageHighlight(passageRange);
14179
+ requestAnimationFrame(() => {
14180
+ pagedEditorRef.current?.scrollToPosition(passageRange.from);
14181
+ });
14182
+ return "passage";
14183
+ }
14184
+ pagedEditorRef.current?.setPassageHighlight(null);
14185
+ const blockRange = resolveFolioAIBlockRange({
14186
+ blockId: blockId_0,
13591
14187
  doc: view_27.state.doc,
13592
14188
  snapshot: snapshot_2
13593
14189
  });
13594
- if (range_4 === null) return false;
13595
- const { from: from_10, to: to_10 } = range_4;
14190
+ if (blockRange === null) return "none";
14191
+ const paraId_0 = getFolioParaIdFromBlockId(blockId_0);
14192
+ if (paraId_0 !== null && pagedEditorRef.current?.scrollToParaId(paraId_0, { highlight: {} })) return "block";
14193
+ const { from: from_10, to: to_10 } = blockRange;
13596
14194
  const $from_1 = view_27.state.doc.resolve(from_10);
13597
14195
  const $to_1 = view_27.state.doc.resolve(to_10);
13598
14196
  view_27.dispatch(view_27.state.tr.setSelection(TextSelection.between($from_1, $to_1)));
13599
14197
  requestAnimationFrame(() => {
13600
14198
  pagedEditorRef.current?.scrollToPosition(from_10);
13601
14199
  });
13602
- return true;
14200
+ return "block";
13603
14201
  },
13604
- getTrackedChanges: () => {
14202
+ clearPassageHighlight: () => {
14203
+ pagedEditorRef.current?.setPassageHighlight(null);
14204
+ },
14205
+ showInDocument: (target_1, snapshot_3) => {
13605
14206
  const view_28 = pagedEditorRef.current?.getView();
13606
- return view_28 ? getTrackedChangesFromDoc(view_28.state.doc) : [];
14207
+ if (!view_28) return false;
14208
+ const range_4 = target_1.type === "textRange" ? resolveFolioAITextRange({
14209
+ range: target_1,
14210
+ doc: view_28.state.doc,
14211
+ snapshot: snapshot_3
14212
+ }) : resolveFolioAIBlockRange({
14213
+ blockId: target_1.blockId,
14214
+ doc: view_28.state.doc,
14215
+ snapshot: snapshot_3
14216
+ });
14217
+ if (range_4 === null) return false;
14218
+ const { from: from_11, to: to_11 } = range_4;
14219
+ const $from_2 = view_28.state.doc.resolve(from_11);
14220
+ const $to_2 = view_28.state.doc.resolve(to_11);
14221
+ view_28.dispatch(view_28.state.tr.setSelection(TextSelection.between($from_2, $to_2)));
14222
+ requestAnimationFrame(() => {
14223
+ pagedEditorRef.current?.scrollToPosition(from_11);
14224
+ });
14225
+ return true;
13607
14226
  },
13608
- getCommentAnchors: () => {
14227
+ getSuggestions: () => {
13609
14228
  const view_29 = pagedEditorRef.current?.getView();
13610
- return view_29 ? getCommentAnchorsFromDoc(view_29.state.doc) : [];
14229
+ return view_29 ? getSuggestions(view_29.state) : [];
13611
14230
  },
13612
- getSelectionText: () => {
14231
+ acceptSuggestion: (suggestionId, options_2) => {
13613
14232
  const view_30 = pagedEditorRef.current?.getView();
13614
- return view_30 ? getSelectedText(view_30.state) : "";
14233
+ if (!view_30) return {
14234
+ accepted: false,
14235
+ appliedAs: null
14236
+ };
14237
+ const appliedAs = getSuggestions(view_30.state).find((s_0) => s_0.suggestionId === suggestionId)?.appliedAs ?? null;
14238
+ const accepted = acceptSuggestion(suggestionId, { author: options_2?.author ?? author })(view_30.state, view_30.dispatch);
14239
+ return {
14240
+ accepted,
14241
+ appliedAs: accepted ? appliedAs : null
14242
+ };
13615
14243
  },
13616
- getPageText: (page_0) => {
14244
+ rejectSuggestion: (suggestionId_0) => {
13617
14245
  const view_31 = pagedEditorRef.current?.getView();
13618
- if (!view_31) return null;
13619
- return getPageTextFromLayout(pagedEditorRef.current?.getEditor()?.getLayout() ?? null, view_31.state.doc, page_0);
14246
+ if (!view_31) return false;
14247
+ return rejectSuggestion(suggestionId_0)(view_31.state, view_31.dispatch);
13620
14248
  },
13621
- getTargetPage: (target_2, snapshot_3) => {
14249
+ scrollToSuggestion: (suggestionId_1) => {
13622
14250
  const view_32 = pagedEditorRef.current?.getView();
13623
- if (!view_32) return null;
13624
- const range_5 = target_2.type === "textRange" ? resolveFolioAITextRange({
14251
+ if (!view_32) return false;
14252
+ const range_5 = findSuggestionRange(view_32.state, suggestionId_1);
14253
+ if (!range_5) return false;
14254
+ const { from: from_12, to: to_12 } = clampRangeToDocSize(view_32.state.doc.content.size, range_5);
14255
+ const $from_3 = view_32.state.doc.resolve(from_12);
14256
+ const $to_3 = view_32.state.doc.resolve(to_12);
14257
+ view_32.dispatch(view_32.state.tr.setSelection(TextSelection.between($from_3, $to_3)));
14258
+ requestAnimationFrame(() => {
14259
+ pagedEditorRef.current?.scrollToPosition(from_12);
14260
+ });
14261
+ return true;
14262
+ },
14263
+ getTrackedChanges: () => {
14264
+ const view_33 = pagedEditorRef.current?.getView();
14265
+ return view_33 ? getTrackedChangesFromDoc(view_33.state.doc) : [];
14266
+ },
14267
+ getCommentAnchors: () => {
14268
+ const view_34 = pagedEditorRef.current?.getView();
14269
+ return view_34 ? getCommentAnchorsFromDoc(view_34.state.doc) : [];
14270
+ },
14271
+ getSelectionText: () => {
14272
+ const view_35 = pagedEditorRef.current?.getView();
14273
+ return view_35 ? getSelectedText(view_35.state) : "";
14274
+ },
14275
+ getPageText: (page_0) => {
14276
+ const view_36 = pagedEditorRef.current?.getView();
14277
+ if (!view_36) return null;
14278
+ return getPageTextFromLayout(pagedEditorRef.current?.getEditor()?.getLayout() ?? null, view_36.state.doc, page_0);
14279
+ },
14280
+ getTargetPage: (target_2, snapshot_4) => {
14281
+ const view_37 = pagedEditorRef.current?.getView();
14282
+ if (!view_37) return null;
14283
+ const range_6 = target_2.type === "textRange" ? resolveFolioAITextRange({
13625
14284
  range: target_2,
13626
- doc: view_32.state.doc,
13627
- snapshot: snapshot_3
14285
+ doc: view_37.state.doc,
14286
+ snapshot: snapshot_4
13628
14287
  }) : resolveFolioAIBlockRange({
13629
14288
  blockId: target_2.blockId,
13630
- doc: view_32.state.doc,
13631
- snapshot: snapshot_3
14289
+ doc: view_37.state.doc,
14290
+ snapshot: snapshot_4
13632
14291
  });
13633
- if (range_5 === null) return null;
13634
- return pagedEditorRef.current?.getPageNumberForPmPos(range_5.from) ?? null;
14292
+ if (range_6 === null) return null;
14293
+ return pagedEditorRef.current?.getPageNumberForPmPos(range_6.from) ?? null;
13635
14294
  },
13636
14295
  getContentControls: (filter = {}) => {
13637
- const view_33 = pagedEditorRef.current?.getView();
13638
- if (!view_33) return [];
13639
- return findBlockSdtMatches(view_33.state.doc, filter).map((match_0) => ({
14296
+ const view_38 = pagedEditorRef.current?.getView();
14297
+ if (!view_38) return [];
14298
+ return findBlockSdtMatches(view_38.state.doc, filter).map((match_0) => ({
13640
14299
  properties: blockSdtAttrsToSdtProperties(match_0.node),
13641
14300
  path: match_0.path,
13642
14301
  pmPos: match_0.pos
13643
14302
  }));
13644
14303
  },
13645
14304
  scrollToContentControl: (filter_0) => {
13646
- const view_34 = pagedEditorRef.current?.getView();
13647
- if (!view_34) return false;
13648
- const match_1 = findBlockSdtMatch(view_34.state.doc, filter_0);
14305
+ const view_39 = pagedEditorRef.current?.getView();
14306
+ if (!view_39) return false;
14307
+ const match_1 = findBlockSdtMatch(view_39.state.doc, filter_0);
13649
14308
  if (!match_1) return false;
13650
14309
  const inside = match_1.pos + 1;
13651
- const $pos = view_34.state.doc.resolve(inside);
13652
- view_34.dispatch(view_34.state.tr.setSelection(TextSelection.near($pos)));
14310
+ const $pos = view_39.state.doc.resolve(inside);
14311
+ view_39.dispatch(view_39.state.tr.setSelection(TextSelection.near($pos)));
13653
14312
  requestAnimationFrame(() => {
13654
14313
  pagedEditorRef.current?.scrollToPosition(inside);
13655
14314
  });
13656
14315
  return true;
13657
14316
  },
13658
- setContentControlContent: (filter_1, input, options_2 = {}) => {
13659
- const view_35 = pagedEditorRef.current?.getView();
13660
- if (!view_35) return false;
13661
- const tr_0 = typeof input === "string" ? setContentControlContentTr(view_35.state, filter_1, input, options_2) : setContentControlContentBlocksTr(view_35.state, filter_1, input, options_2);
14317
+ setContentControlContent: (filter_1, input, options_3 = {}) => {
14318
+ const view_40 = pagedEditorRef.current?.getView();
14319
+ if (!view_40) return false;
14320
+ const tr_0 = typeof input === "string" ? setContentControlContentTr(view_40.state, filter_1, input, options_3) : setContentControlContentBlocksTr(view_40.state, filter_1, input, options_3);
13662
14321
  if (!tr_0) return false;
13663
- view_35.dispatch(tr_0);
14322
+ view_40.dispatch(tr_0);
13664
14323
  return true;
13665
14324
  },
13666
- setContentControlValue: (filter_2, input_0, options_3 = {}) => {
13667
- const view_36 = pagedEditorRef.current?.getView();
13668
- if (!view_36) return false;
13669
- const tr_1 = setContentControlValueTr(view_36.state, filter_2, input_0, options_3);
14325
+ setContentControlValue: (filter_2, input_0, options_4 = {}) => {
14326
+ const view_41 = pagedEditorRef.current?.getView();
14327
+ if (!view_41) return false;
14328
+ const tr_1 = setContentControlValueTr(view_41.state, filter_2, input_0, options_4);
13670
14329
  if (!tr_1) return false;
13671
- view_36.dispatch(tr_1);
14330
+ view_41.dispatch(tr_1);
13672
14331
  return true;
13673
14332
  },
13674
- removeContentControl: (filter_3, options_4 = {}) => {
13675
- const view_37 = pagedEditorRef.current?.getView();
13676
- if (!view_37) return false;
13677
- const tr_2 = removeContentControlTr(view_37.state, filter_3, options_4);
14333
+ removeContentControl: (filter_3, options_5 = {}) => {
14334
+ const view_42 = pagedEditorRef.current?.getView();
14335
+ if (!view_42) return false;
14336
+ const tr_2 = removeContentControlTr(view_42.state, filter_3, options_5);
13678
14337
  if (!tr_2) return false;
13679
- view_37.dispatch(tr_2);
14338
+ view_42.dispatch(tr_2);
13680
14339
  return true;
13681
14340
  }
13682
14341
  }), [
@@ -13693,7 +14352,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13693
14352
  replaceComments,
13694
14353
  commentsRef,
13695
14354
  commentsDirtyRef,
13696
- hfEditPosition,
14355
+ getActiveEditorStory,
13697
14356
  refreshBodyHistoryAvailability
13698
14357
  ]);
13699
14358
  const getHfTargetElement = useCallback((pos_0) => {
@@ -13706,6 +14365,17 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13706
14365
  value: mode_0,
13707
14366
  label: t(DISPLAY_MODE_LABEL_KEYS[mode_0])
13708
14367
  })), [t]);
14368
+ const activeHistoryAvailability = (() => {
14369
+ if (activeNoteStory) return {
14370
+ canRedo: pagedEditorRef.current?.canRedo() ?? false,
14371
+ canUndo: pagedEditorRef.current?.canUndo() ?? false
14372
+ };
14373
+ if (hfEditPosition) return {
14374
+ canRedo: history.canRedo,
14375
+ canUndo: history.canUndo
14376
+ };
14377
+ return bodyHistoryAvailability;
14378
+ })();
13709
14379
  const toolbarChildren = toolbarExtra ?? null;
13710
14380
  const visibleCommentAuthorCount = commentAuthors.filter((commentAuthor) => visibleCommentAuthorSet.has(commentAuthor)).length;
13711
14381
  const allCommentAuthorsVisible = commentAuthors.length > 0 && showCommentsSidebar && visibleCommentAuthorCount === commentAuthors.length;
@@ -13747,39 +14417,39 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13747
14417
  if (isDisplayMode(value)) setDisplayMode(value);
13748
14418
  }, [setDisplayMode]);
13749
14419
  const handleAcceptActiveChange = useCallback(() => {
13750
- const view_38 = pagedEditorRef.current?.getView();
13751
- if (!view_38) return;
13752
- const { from: from_11, to: to_11 } = view_38.state.selection;
13753
- const range_6 = findChangeAtPosition(view_38.state, from_11, to_11);
13754
- acceptChange(range_6.from, range_6.to)(view_38.state, view_38.dispatch);
14420
+ const view_43 = pagedEditorRef.current?.getView();
14421
+ if (!view_43) return;
14422
+ const { from: from_13, to: to_13 } = view_43.state.selection;
14423
+ const range_7 = findChangeAtPosition(view_43.state, from_13, to_13);
14424
+ acceptChange(range_7.from, range_7.to)(view_43.state, view_43.dispatch);
13755
14425
  }, []);
13756
14426
  const handleRejectActiveChange = useCallback(() => {
13757
- const view_39 = pagedEditorRef.current?.getView();
13758
- if (!view_39) return;
13759
- const { from: from_12, to: to_12 } = view_39.state.selection;
13760
- const range_7 = findChangeAtPosition(view_39.state, from_12, to_12);
13761
- rejectChange(range_7.from, range_7.to)(view_39.state, view_39.dispatch);
14427
+ const view_44 = pagedEditorRef.current?.getView();
14428
+ if (!view_44) return;
14429
+ const { from: from_14, to: to_14 } = view_44.state.selection;
14430
+ const range_8 = findChangeAtPosition(view_44.state, from_14, to_14);
14431
+ rejectChange(range_8.from, range_8.to)(view_44.state, view_44.dispatch);
13762
14432
  }, []);
13763
14433
  const handlePreviousChange = useCallback(() => {
13764
- const view_40 = pagedEditorRef.current?.getView();
13765
- if (!view_40) return;
13766
- const { from: from_13 } = view_40.state.selection;
13767
- const change = findPreviousChange(view_40.state, from_13);
14434
+ const view_45 = pagedEditorRef.current?.getView();
14435
+ if (!view_45) return;
14436
+ const { from: from_15 } = view_45.state.selection;
14437
+ const change = findPreviousChange(view_45.state, from_15);
13768
14438
  if (!change) return;
13769
- view_40.dispatch(view_40.state.tr.setSelection(TextSelection.create(view_40.state.doc, change.from, change.to)));
13770
- view_40.focus();
14439
+ view_45.dispatch(view_45.state.tr.setSelection(TextSelection.create(view_45.state.doc, change.from, change.to)));
14440
+ view_45.focus();
13771
14441
  requestAnimationFrame(() => {
13772
14442
  pagedEditorRef.current?.scrollToPosition(change.from);
13773
14443
  });
13774
14444
  }, []);
13775
14445
  const handleNextChange = useCallback(() => {
13776
- const view_41 = pagedEditorRef.current?.getView();
13777
- if (!view_41) return;
13778
- const { to: to_13 } = view_41.state.selection;
13779
- const change_0 = findNextChange(view_41.state, to_13);
14446
+ const view_46 = pagedEditorRef.current?.getView();
14447
+ if (!view_46) return;
14448
+ const { to: to_15 } = view_46.state.selection;
14449
+ const change_0 = findNextChange(view_46.state, to_15);
13780
14450
  if (!change_0) return;
13781
- view_41.dispatch(view_41.state.tr.setSelection(TextSelection.create(view_41.state.doc, change_0.from, change_0.to)));
13782
- view_41.focus();
14451
+ view_46.dispatch(view_46.state.tr.setSelection(TextSelection.create(view_46.state.doc, change_0.from, change_0.to)));
14452
+ view_46.focus();
13783
14453
  requestAnimationFrame(() => {
13784
14454
  pagedEditorRef.current?.scrollToPosition(change_0.from);
13785
14455
  });
@@ -13949,8 +14619,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13949
14619
  requestAnimationFrame(syncCommentHighlightStyles);
13950
14620
  }, [onScrollTopChange, syncCommentHighlightStyles]);
13951
14621
  const handlePagedSelectionChange = useCallback((_from, _to) => {
13952
- const view_42 = getActiveEditorView() ?? pagedEditorRef.current?.getView() ?? null;
13953
- handleSelectionChange(view_42 ? extractSelectionState(view_42.state) : null);
14622
+ const view_47 = getActiveEditorView() ?? pagedEditorRef.current?.getView() ?? null;
14623
+ handleSelectionChange(view_47 ? extractSelectionState(view_47.state) : null);
13954
14624
  }, [getActiveEditorView, handleSelectionChange]);
13955
14625
  const handleTotalPagesChange = useCallback((totalPages) => {
13956
14626
  setScrollPageInfo((previous) => updateScrollPageTotal(previous, totalPages));
@@ -13970,14 +14640,14 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13970
14640
  setActiveCommentId,
13971
14641
  updateComments
13972
14642
  ]);
13973
- const handleCommentReply = useCallback((id_2, text_5) => {
13974
- updateComments((previous_2) => [...previous_2, createComment(text_5, author, id_2)]);
14643
+ const handleCommentReply = useCallback((id_2, text_6) => {
14644
+ updateComments((previous_2) => [...previous_2, createComment(text_6, author, id_2)]);
13975
14645
  }, [author, updateComments]);
13976
14646
  const handleAddComment = useCallback((addText) => {
13977
14647
  const comment_3 = createComment(addText, author);
13978
- const view_43 = pagedEditorRef.current?.getView();
13979
- if (!view_43 || !commentSelectionRange) return false;
13980
- if (!applyCommentMarkRange(view_43, commentSelectionRange, comment_3.id, { replacePending: true })) return false;
14648
+ const view_48 = pagedEditorRef.current?.getView();
14649
+ if (!view_48 || !commentSelectionRange) return false;
14650
+ if (!applyCommentMarkRange(view_48, commentSelectionRange, comment_3.id, { replacePending: true })) return false;
13981
14651
  const commentAuthor_2 = getCommentAuthorKey(comment_3.author);
13982
14652
  setVisibleCommentAuthors((current) => {
13983
14653
  if (current === null) return null;
@@ -14007,12 +14677,12 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14007
14677
  syncCommentHighlightStyles,
14008
14678
  updateComments
14009
14679
  ]);
14010
- const handleTrackedChangeReply = useCallback((revisionId_2, text_6) => {
14011
- updateComments((previous_4) => [...previous_4, createComment(text_6, author, revisionId_2)]);
14680
+ const handleTrackedChangeReply = useCallback((revisionId_2, text_7) => {
14681
+ updateComments((previous_4) => [...previous_4, createComment(text_7, author, revisionId_2)]);
14012
14682
  }, [author, updateComments]);
14013
14683
  const handleCancelAddComment = useCallback(() => {
14014
- const view_44 = pagedEditorRef.current?.getView();
14015
- if (view_44 && commentSelectionRange) removePendingCommentMarkRange(view_44, commentSelectionRange);
14684
+ const view_49 = pagedEditorRef.current?.getView();
14685
+ if (view_49 && commentSelectionRange) removePendingCommentMarkRange(view_49, commentSelectionRange);
14016
14686
  setIsAddingComment(false);
14017
14687
  setCommentSelectionRange(null);
14018
14688
  setAddCommentYPosition(null);
@@ -14022,18 +14692,27 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14022
14692
  setCommentSelectionRange,
14023
14693
  setIsAddingComment
14024
14694
  ]);
14025
- const handleSidebarAcceptChange = useCallback((from_14, to_14) => {
14026
- const view_45 = pagedEditorRef.current?.getView();
14027
- if (!view_45) return;
14028
- acceptChange(from_14, to_14)(view_45.state, view_45.dispatch);
14695
+ const resolveSidebarChangeRevisionId = useCallback((from_16, to_16) => {
14696
+ return trackedChangesRef.current.find((candidate) => {
14697
+ return candidate.from === from_16 && candidate.to === to_16;
14698
+ })?.revisionId ?? null;
14699
+ }, []);
14700
+ const handleSidebarAcceptChange = useCallback((from_17, to_17) => {
14701
+ const view_50 = pagedEditorRef.current?.getView();
14702
+ if (!view_50) return;
14703
+ const revisionId_3 = resolveSidebarChangeRevisionId(from_17, to_17);
14704
+ if (revisionId_3 === null) return;
14705
+ acceptAIEditRevision(revisionId_3)(view_50.state, view_50.dispatch);
14029
14706
  extractTrackedChanges();
14030
- }, [extractTrackedChanges]);
14031
- const handleSidebarRejectChange = useCallback((from_15, to_15) => {
14032
- const view_46 = pagedEditorRef.current?.getView();
14033
- if (!view_46) return;
14034
- rejectChange(from_15, to_15)(view_46.state, view_46.dispatch);
14707
+ }, [extractTrackedChanges, resolveSidebarChangeRevisionId]);
14708
+ const handleSidebarRejectChange = useCallback((from_18, to_18) => {
14709
+ const view_51 = pagedEditorRef.current?.getView();
14710
+ if (!view_51) return;
14711
+ const revisionId_4 = resolveSidebarChangeRevisionId(from_18, to_18);
14712
+ if (revisionId_4 === null) return;
14713
+ rejectAIEditRevision(revisionId_4)(view_51.state, view_51.dispatch);
14035
14714
  extractTrackedChanges();
14036
- }, [extractTrackedChanges]);
14715
+ }, [extractTrackedChanges, resolveSidebarChangeRevisionId]);
14037
14716
  const commentsPageWidth = history.state?.package.document.finalSectionProperties?.pageWidth;
14038
14717
  const commentsSidebarOverlay = useMemo(() => {
14039
14718
  if (!showCommentsSidebar) return;
@@ -14077,8 +14756,6 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14077
14756
  showCommentsSidebar,
14078
14757
  visibleComments
14079
14758
  ]);
14080
- let activeHfRId = hfEditIsFirstPage ? activeFirstFooterRId : activeFooterRId;
14081
- if (hfEditPosition === "header") activeHfRId = hfEditIsFirstPage ? activeFirstHeaderRId : activeHeaderRId;
14082
14759
  const getActiveHfView = useCallback(() => activeHfRId ? pagedEditorRef.current?.getHfView(activeHfRId) ?? null : null, [activeHfRId]);
14083
14760
  const handleOutlineHeadingClick = useCallback((pmPos) => {
14084
14761
  pagedEditorRef.current?.scrollToPosition(pmPos);
@@ -14102,10 +14779,15 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14102
14779
  handleContextMenuAction(action_3);
14103
14780
  }, [handleContextMenuAction]);
14104
14781
  const getBodyEditorView = useCallback(() => pagedEditorRef.current?.getView() ?? null, []);
14782
+ const getContentControlEventRoot = useCallback(() => {
14783
+ if (readOnly) return null;
14784
+ const root = containerRef.current?.querySelector(".paged-editor__pages");
14785
+ return root instanceof HTMLElement ? root : null;
14786
+ }, [readOnly]);
14105
14787
  const closeTableProperties = useCallback(() => setTablePropsOpen(false), []);
14106
14788
  const applyTableProperties = useCallback((props_0) => {
14107
- const view_47 = getActiveEditorView();
14108
- if (view_47) setTableProperties(props_0)(view_47.state, view_47.dispatch);
14789
+ const view_52 = getActiveEditorView();
14790
+ if (view_52) setTableProperties(props_0)(view_52.state, view_52.dispatch);
14109
14791
  }, [getActiveEditorView]);
14110
14792
  const closeImagePosition = useCallback(() => setImagePositionOpen(false), [setImagePositionOpen]);
14111
14793
  const closeImageProperties = useCallback(() => setImagePropsOpen(false), [setImagePropsOpen]);
@@ -14113,8 +14795,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14113
14795
  const closeFootnoteProperties = useCallback(() => setFootnotePropsOpen(false), []);
14114
14796
  const closeInsertSymbol = useCallback(() => setShowInsertSymbol(false), []);
14115
14797
  const insertSymbol = useCallback((symbol) => {
14116
- const view_48 = getActiveEditorView();
14117
- if (view_48) view_48.dispatch(view_48.state.tr.insertText(symbol).scrollIntoView());
14798
+ const view_53 = getActiveEditorView();
14799
+ if (view_53) view_53.dispatch(view_53.state.tr.insertText(symbol).scrollIntoView());
14118
14800
  }, [getActiveEditorView]);
14119
14801
  const imagePropertiesCurrentData = useMemo(() => buildImagePropertiesData(state.pmImageContext), [state.pmImageContext]);
14120
14802
  const currentFindResult = findResultRef.current;
@@ -14281,8 +14963,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14281
14963
  onFormat: handleFormat,
14282
14964
  onUndo: undoActiveEditor,
14283
14965
  onRedo: redoActiveEditor,
14284
- canUndo: hfEditPosition ? history.canUndo : bodyHistoryAvailability.canUndo,
14285
- canRedo: hfEditPosition ? history.canRedo : bodyHistoryAvailability.canRedo,
14966
+ canUndo: activeHistoryAvailability.canUndo,
14967
+ canRedo: activeHistoryAvailability.canRedo,
14286
14968
  disabled: readOnly,
14287
14969
  theme: history.state.package.theme || theme || null,
14288
14970
  fontFamilies,
@@ -14405,13 +15087,22 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14405
15087
  firstPageHeaderContentRId: activeFirstHeaderRId,
14406
15088
  firstPageFooterContentRId: activeFirstFooterRId,
14407
15089
  ...history.state.package.styles ? { styles: history.state.package.styles } : {},
14408
- onHeaderFooterDoubleClick: showHeaderFooterEditing ? handleHeaderFooterDoubleClick : void 0,
15090
+ onHeaderFooterDoubleClick: showHeaderFooterEditing ? handleHeaderFooterStoryOpen : void 0,
14409
15091
  hfEditMode: hfEditPosition,
15092
+ activeHeaderFooterRId: activeHfRId,
14410
15093
  onBodyClick: handleBodyClick,
15094
+ onActiveNoteStoryChange: handleActiveNoteStoryChange,
14411
15095
  zoom,
15096
+ showMarginGuides,
15097
+ ...marginGuideColor !== void 0 ? { marginGuideColor } : {},
14412
15098
  readOnly,
14413
15099
  onDocumentChange: handleDocumentChange,
14414
15100
  extensionManager,
15101
+ suggestionModeActive: editingMode === "suggesting",
15102
+ suggestionAuthor: author,
15103
+ ...onCopy !== void 0 ? { onCopy } : {},
15104
+ ...onCut !== void 0 ? { onCut } : {},
15105
+ ...onPaste !== void 0 ? { onPaste } : {},
14415
15106
  ...onReadonlyEditAttempt !== void 0 ? { onReadOnlyEditAttempt: onReadonlyEditAttempt } : {},
14416
15107
  onSelectionChange: handlePagedSelectionChange,
14417
15108
  ...onSelectionTextChange !== void 0 ? { onSelectionTextChange } : {},
@@ -14440,8 +15131,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14440
15131
  onMouseDown: (e_1) => {
14441
15132
  e_1.preventDefault();
14442
15133
  e_1.stopPropagation();
14443
- const view_49 = pagedEditorRef.current?.getView();
14444
- if (!view_49) {
15134
+ const view_54 = pagedEditorRef.current?.getView();
15135
+ if (!view_54) {
14445
15136
  setFloatingCommentBtn(null);
14446
15137
  return;
14447
15138
  }
@@ -14449,9 +15140,9 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14449
15140
  from: floatingCommentBtn.from,
14450
15141
  to: floatingCommentBtn.to
14451
15142
  };
14452
- const currentSelection = view_49.state.selection;
15143
+ const currentSelection = view_54.state.selection;
14453
15144
  const safeRange = resolveCommentCreationRange({
14454
- docSize: view_49.state.doc.content.size,
15145
+ docSize: view_54.state.doc.content.size,
14455
15146
  capturedRange,
14456
15147
  currentRange: {
14457
15148
  from: currentSelection.from,
@@ -14465,7 +15156,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14465
15156
  return;
14466
15157
  }
14467
15158
  setCommentSelectionRange(safeRange);
14468
- if (!applyCommentMarkRange(view_49, safeRange, -1, { selectEnd: true })) {
15159
+ if (!applyCommentMarkRange(view_54, safeRange, -1, { selectEnd: true })) {
14469
15160
  setCommentSelectionRange(null);
14470
15161
  setFloatingCommentBtn(null);
14471
15162
  return;
@@ -14595,7 +15286,10 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14595
15286
  onClose: handleContextMenuClose
14596
15287
  })
14597
15288
  }),
14598
- /* @__PURE__ */ jsx(ContentControlWidgetsOverlay, { getEditorView: getBodyEditorView }),
15289
+ /* @__PURE__ */ jsx(ContentControlWidgetsOverlay, {
15290
+ getEventRoot: getContentControlEventRoot,
15291
+ getEditorView: getBodyEditorView
15292
+ }),
14599
15293
  /* @__PURE__ */ jsx(DocxEditorDialogs, {
14600
15294
  findReplace: findReplaceDialog,
14601
15295
  tableProperties: tablePropertiesDialog,