@stll/folio-react 0.10.1 → 0.11.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,6 +7,7 @@ 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";
@@ -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";
@@ -36,15 +37,11 @@ import { formatPx, pixelsToTwips, pointsToHalfPoints, twipsToPixels } from "@stl
36
37
  import { HistoryManager, classifyHistoryShortcut } from "@stll/folio-core/managers/HistoryManager";
37
38
  import { TableSelectionManager } from "@stll/folio-core/managers/TableSelectionManager";
38
39
  import { createPortal } from "react-dom";
39
- import { EditorState, NodeSelection, Selection, TextSelection as TextSelection$1 } from "prosemirror-state";
40
+ import { NodeSelection, Selection, TextSelection as TextSelection$1 } from "prosemirror-state";
40
41
  import { CellSelection } from "prosemirror-tables";
41
- import { EditorView } from "prosemirror-view";
42
- import { headerFooterToProseDoc } from "@stll/folio-core/prosemirror/conversion/toProseDoc";
43
- import { ensureBaseDirectionInState } from "@stll/folio-core/prosemirror/extensions/features/AutoBidiDetectionExtension";
44
- import { ensureParaIdsInState } from "@stll/folio-core/prosemirror/extensions/features/ParaIdAllocatorExtension";
45
- import { createDocumentStylesPlugin } from "@stll/folio-core/prosemirror/plugins/documentStyles";
46
- import { schema as schema$1 } from "@stll/folio-core/prosemirror/schema";
42
+ import { createHeaderFooterEditorManager } from "@stll/folio-core/controller/headerFooterEditorManager";
47
43
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
44
+ import { createNoteEditorManager } from "@stll/folio-core/controller/noteEditorManager";
48
45
  import { createFolioEditor } from "@stll/folio-core/controller/folioEditor";
49
46
  import { createFolioEditorEmitter } from "@stll/folio-core/controller/folioEditorEvents";
50
47
  import { createLatestRequestGate } from "@stll/folio-core/controller/latestRequestGate";
@@ -58,6 +55,7 @@ import { templatePreviewDirtyRange } from "@stll/folio-core/layout-bridge/conver
58
55
  import { clickToPositionDom } from "@stll/folio-core/layout-bridge/dom/clickToPositionDom";
59
56
  import { findBodyEmptyRuns, findBodyPmAnchor, findBodyPmAnchors, findBodyPmSpans } from "@stll/folio-core/layout-bridge/dom/findBodyPmSpans";
60
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";
61
59
  import { clickToPosition } from "@stll/folio-core/layout-bridge/engine/clickToPosition";
62
60
  import { getPageTop, hitTestFragment, hitTestTableCell } from "@stll/folio-core/layout-bridge/engine/hitTest";
63
61
  import { clearAllCaches, resetCanvasContext } from "@stll/folio-core/layout-bridge/engine/measuring";
@@ -80,9 +78,12 @@ import { expectImageAttrs, expectTableAttrs, expectTableCellAttrs, mergeImageAtt
80
78
  import { extractEmbeddedFonts } from "@stll/folio-core/fonts/embeddedFonts";
81
79
  import { panic } from "better-result";
82
80
  import { collectRemoteSelections, createHiddenEditorManager, createHiddenEditorState } from "@stll/folio-core/controller/hiddenEditorManager";
83
- import { clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange } from "@stll/folio-core/ai-edits/blockRange";
81
+ import { loadCollaborationModules } from "@stll/folio-core/controller/collaborationModules";
82
+ import { clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange } from "@stll/folio-core/ai-edits/blockRange";
83
+ import { getFolioParaIdFromBlockId } from "@stll/folio-core/types/block-id";
84
84
  import { getPageTextFromLayout } from "@stll/folio-core/paged-layout/pageText";
85
- import { CONTENT_CONTROL_WIDGET_EVENT_NAME, dispatchDatePick, dispatchDropdownPick } from "@stll/folio-core/prosemirror/plugins/contentControlWidgets";
85
+ import { ContentControlWidgetController } from "@stll/folio-core/controller/contentControlWidgetController";
86
+ import { createDefaultFindOptions, findInDocument } from "@stll/folio-core/utils/findReplace";
86
87
  import { ErrorManager } from "@stll/folio-core/managers/ErrorManager";
87
88
  import { ContextMenuManager } from "@stll/folio-core/managers/ContextMenuManager";
88
89
  import { DocumentLoaderManager } from "@stll/folio-core/managers/DocumentLoaderManager";
@@ -197,7 +198,7 @@ function useDocumentHistory(document, t0) {
197
198
  $[1] = t1;
198
199
  } else t1 = $[1];
199
200
  const options = t1;
200
- const isEqual = _temp$10;
201
+ const isEqual = _temp$11;
201
202
  let t2;
202
203
  if ($[2] !== options) {
203
204
  t2 = {
@@ -209,7 +210,7 @@ function useDocumentHistory(document, t0) {
209
210
  } else t2 = $[3];
210
211
  return useHistory(document, t2);
211
212
  }
212
- function _temp$10(a, b) {
213
+ function _temp$11(a, b) {
213
214
  if (a === b) return true;
214
215
  const aPackage = a?.package;
215
216
  const bPackage = b?.package;
@@ -311,54 +312,7 @@ function useTableSelection(t0) {
311
312
  }
312
313
  //#endregion
313
314
  //#region src/components/HiddenHeaderFooterPMs.tsx
314
- /**
315
- * HiddenHeaderFooterPMs — persistent off-screen ProseMirror EditorViews for
316
- * every distinct header/footer part in the loaded document.
317
- *
318
- * Mounts one hidden EditorView per distinct HF `rId` from
319
- * `Document.package.headers ∪ Document.package.footers`. The views never
320
- * become the visible HF renderer — the painter is the sole visible HF
321
- * renderer in both edit and non-edit modes. The persistent views own the
322
- * source of truth for HF content while the document is loaded; the
323
- * painter reads each rId's `view.state.doc` through
324
- * `convertHeaderFooterPmDocToContent`.
325
- *
326
- * Slot keying is by `rId`, NOT by `(hdrFtrType, kind)` — two sections that
327
- * share a header by referencing the same `rId` (ECMA-376 §17.10.1
328
- * sharing-by-reference) share one EditorView, so an edit on any painted
329
- * instance propagates to every painted instance in one layout pass.
330
- *
331
- * Unlike upstream's in-place `hf.content` mutation, folio's history-immutable
332
- * model surfaces every transaction through `onTransaction`; the parent
333
- * (`useHeaderFooterEditor` / `DocxEditor`) is the only place that pushes
334
- * Document changes through history.
335
- */
336
- function buildInitialState(hf, styles, theme, mgr) {
337
- const proseDocOptions = {};
338
- if (styles) proseDocOptions.styles = styles;
339
- if (theme !== void 0) proseDocOptions.theme = theme;
340
- const pmDoc = headerFooterToProseDoc(hf.content, proseDocOptions);
341
- const styleResolverPlugin = createDocumentStylesPlugin(styles);
342
- return ensureBaseDirectionInState(ensureParaIdsInState(EditorState.create({
343
- doc: pmDoc,
344
- schema: schema$1,
345
- plugins: [...mgr.getPlugins(), styleResolverPlugin]
346
- })));
347
- }
348
- function enumerateHfSlotsFromParts({ headers, footers }) {
349
- const out = [];
350
- if (headers) for (const rId of headers.keys()) out.push({
351
- rId,
352
- kind: "header"
353
- });
354
- if (footers) {
355
- for (const rId of footers.keys()) if (!headers || !headers.has(rId)) out.push({
356
- rId,
357
- kind: "footer"
358
- });
359
- }
360
- return out;
361
- }
315
+ /** Thin React binding for core's persistent header/footer editor manager. */
362
316
  const HOST_STYLES = {
363
317
  position: "fixed",
364
318
  left: -9999,
@@ -368,105 +322,41 @@ const HOST_STYLES = {
368
322
  pointerEvents: "none"
369
323
  };
370
324
  const HiddenHeaderFooterPMs = memo(forwardRef(function HiddenHeaderFooterPMs({ document, styles, theme, onTransaction }, ref) {
371
- const onTransactionRef = useRef(onTransaction);
372
- onTransactionRef.current = onTransaction;
373
325
  const hostRef = useRef(null);
374
- const mountedRef = useRef(/* @__PURE__ */ new Map());
375
- const managersRef = useRef(/* @__PURE__ */ new Map());
376
326
  const documentRef = useRef(document);
327
+ const stylesRef = useRef(styles);
328
+ const themeRef = useRef(theme);
329
+ const onTransactionRef = useRef(onTransaction);
377
330
  documentRef.current = document;
378
- const resolveHf = useCallback((rId, kind) => {
379
- const pkg = documentRef.current?.package;
380
- if (!pkg) return null;
381
- return (kind === "header" ? pkg.headers : pkg.footers)?.get(rId) ?? null;
382
- }, []);
331
+ stylesRef.current = styles;
332
+ themeRef.current = theme;
333
+ onTransactionRef.current = onTransaction;
334
+ const managerRef = useRef(null);
335
+ managerRef.current ??= createHeaderFooterEditorManager({
336
+ getHost: () => hostRef.current,
337
+ getDocument: () => documentRef.current,
338
+ getStyles: () => stylesRef.current,
339
+ getTheme: () => themeRef.current,
340
+ onTransaction: ({ rId, kind, view, docChanged, selectionChanged }) => {
341
+ onTransactionRef.current?.(rId, kind, view, docChanged, selectionChanged);
342
+ }
343
+ });
383
344
  const headers = document?.package.headers;
384
345
  const footers = document?.package.footers;
385
- const slots = useMemo(() => enumerateHfSlotsFromParts({
386
- headers,
387
- footers
388
- }), [headers, footers]);
389
346
  useEffect(() => {
390
- if (!hostRef.current) return;
391
- const host = hostRef.current;
392
- const want = new Map(slots.map((s) => [s.rId, s]));
393
- const have = mountedRef.current;
394
- for (const [rId_0, mounted] of have) if (!want.has(rId_0)) {
395
- mounted.view.destroy();
396
- mounted.mountNode.remove();
397
- have.delete(rId_0);
398
- managersRef.current.delete(rId_0);
399
- }
400
- for (const slot of slots) {
401
- const hf = resolveHf(slot.rId, slot.kind);
402
- if (!hf) continue;
403
- const existing = have.get(slot.rId);
404
- if (existing) {
405
- if (existing.appliedHf === hf && existing.appliedContent === hf.content) continue;
406
- const mgr = managersRef.current.get(slot.rId);
407
- if (!mgr) continue;
408
- const newState = buildInitialState(hf, styles, theme, mgr);
409
- existing.view.updateState(newState);
410
- existing.appliedHf = hf;
411
- existing.appliedContent = hf.content;
412
- continue;
413
- }
414
- const mgr_0 = new ExtensionManager(createStarterKit());
415
- mgr_0.buildSchema();
416
- mgr_0.initializeRuntime();
417
- managersRef.current.set(slot.rId, mgr_0);
418
- const node = host.ownerDocument.createElement("div");
419
- node.dataset["hfRId"] = slot.rId;
420
- node.dataset["hfKind"] = slot.kind;
421
- host.append(node);
422
- const state = buildInitialState(hf, styles, theme, mgr_0);
423
- const slotRId = slot.rId;
424
- const slotKind = slot.kind;
425
- const view = new EditorView(node, {
426
- state,
427
- dispatchTransaction(tr) {
428
- const newState_0 = view.state.apply(tr);
429
- view.updateState(newState_0);
430
- onTransactionRef.current?.(slotRId, slotKind, view, tr.docChanged, tr.selectionSet);
431
- }
432
- });
433
- have.set(slot.rId, {
434
- rId: slot.rId,
435
- kind: slot.kind,
436
- view,
437
- mountNode: node,
438
- appliedHf: hf,
439
- appliedContent: hf.content
440
- });
441
- }
347
+ managerRef.current?.sync();
442
348
  }, [
443
- slots,
444
- resolveHf,
349
+ headers,
350
+ footers,
445
351
  styles,
446
352
  theme
447
353
  ]);
448
- useEffect(() => {
449
- const have_0 = mountedRef.current;
450
- const mgrs = managersRef.current;
451
- return () => {
452
- for (const { view: view_0, mountNode } of have_0.values()) {
453
- view_0.destroy();
454
- mountNode.remove();
455
- }
456
- have_0.clear();
457
- mgrs.clear();
458
- };
354
+ useEffect(() => () => {
355
+ managerRef.current?.destroy();
459
356
  }, []);
460
357
  useImperativeHandle(ref, () => ({
461
- getView(rId_1) {
462
- return mountedRef.current.get(rId_1)?.view ?? null;
463
- },
464
- listSlots() {
465
- return [...mountedRef.current.values()].map(({ rId: rId_2, kind: kind_0 }) => ({
466
- rId: rId_2,
467
- kind: kind_0
468
- }));
469
- }
358
+ getView: (rId) => managerRef.current?.getView(rId) ?? null,
359
+ listSlots: () => managerRef.current?.listSlots() ?? []
470
360
  }), []);
471
361
  return /* @__PURE__ */ jsx("div", {
472
362
  ref: hostRef,
@@ -475,6 +365,292 @@ const HiddenHeaderFooterPMs = memo(forwardRef(function HiddenHeaderFooterPMs({ d
475
365
  }));
476
366
  HiddenHeaderFooterPMs.displayName = "HiddenHeaderFooterPMs";
477
367
  //#endregion
368
+ //#region src/components/NoteStoryEditor.tsx
369
+ /** Thin React surface over core's persistent note-story editor manager. */
370
+ const panelStyle = {
371
+ position: "absolute",
372
+ right: 24,
373
+ bottom: 24,
374
+ width: "min(560px, calc(100% - 48px))",
375
+ maxHeight: "45%",
376
+ overflow: "auto",
377
+ zIndex: 30,
378
+ background: "var(--doc-canvas, #fff)",
379
+ color: "var(--doc-canvas-text, #000)",
380
+ border: "1px solid var(--doc-border, rgba(0, 0, 0, 0.18))",
381
+ borderRadius: 6,
382
+ boxShadow: "0 8px 28px rgba(0, 0, 0, 0.18)"
383
+ };
384
+ const headerStyle = {
385
+ position: "sticky",
386
+ top: 0,
387
+ zIndex: 1,
388
+ display: "flex",
389
+ alignItems: "center",
390
+ justifyContent: "space-between",
391
+ padding: "8px 12px",
392
+ background: "var(--doc-canvas, #fff)",
393
+ borderBottom: "1px solid var(--doc-border, rgba(0, 0, 0, 0.12))",
394
+ fontSize: 12,
395
+ fontWeight: 600
396
+ };
397
+ const hostStyle = {
398
+ padding: "12px 16px",
399
+ minHeight: 72
400
+ };
401
+ const EMPTY_PLUGINS$1 = [];
402
+ const NoteStoryEditor = forwardRef(function NoteStoryEditor(t0, ref) {
403
+ const $ = c(51);
404
+ const { document, onActiveChange, onDocumentChange, onStoryChange, plugins, styles, suggestionAuthor, suggestionModeActive, theme } = t0;
405
+ const t = useTranslations("folio");
406
+ const resolvedPlugins = plugins ?? EMPTY_PLUGINS$1;
407
+ const isSuggestionModeActive = suggestionModeActive ?? false;
408
+ const hostRef = useRef(null);
409
+ const documentRef = useRef(document);
410
+ const stylesRef = useRef(styles);
411
+ const themeRef = useRef(theme);
412
+ const pluginsRef = useRef(resolvedPlugins);
413
+ const onDocumentChangeRef = useRef(onDocumentChange);
414
+ const onActiveChangeRef = useRef(onActiveChange);
415
+ const onStoryChangeRef = useRef(onStoryChange);
416
+ const [active, setActive] = useState(null);
417
+ const managerRef = useRef(null);
418
+ const footnotes = document?.package.footnotes;
419
+ const endnotes = document?.package.endnotes;
420
+ let t1;
421
+ if ($[0] !== active || $[1] !== document || $[2] !== onActiveChange || $[3] !== onDocumentChange || $[4] !== onStoryChange || $[5] !== resolvedPlugins || $[6] !== styles || $[7] !== theme) {
422
+ t1 = () => {
423
+ documentRef.current = document;
424
+ stylesRef.current = styles;
425
+ themeRef.current = theme;
426
+ pluginsRef.current = resolvedPlugins;
427
+ onDocumentChangeRef.current = onDocumentChange;
428
+ onActiveChangeRef.current = onActiveChange;
429
+ onStoryChangeRef.current = onStoryChange;
430
+ if (managerRef.current === null) managerRef.current = createNoteEditorManager({
431
+ getDocument: () => documentRef.current,
432
+ getHost: () => hostRef.current,
433
+ getPlugins: () => pluginsRef.current,
434
+ getStyles: () => stylesRef.current,
435
+ getTheme: () => themeRef.current,
436
+ onTransaction: (t2) => {
437
+ const { docChanged, selectionChanged, view } = t2;
438
+ if (docChanged) {
439
+ const current = documentRef.current;
440
+ if (current) onDocumentChangeRef.current(managerRef.current?.snapshotDocument(current) ?? current);
441
+ }
442
+ onStoryChangeRef.current(view, docChanged, selectionChanged);
443
+ }
444
+ });
445
+ const manager = managerRef.current;
446
+ manager.sync();
447
+ if (active && !manager?.getActive()) {
448
+ setActive(null);
449
+ onActiveChangeRef.current(null);
450
+ }
451
+ };
452
+ $[0] = active;
453
+ $[1] = document;
454
+ $[2] = onActiveChange;
455
+ $[3] = onDocumentChange;
456
+ $[4] = onStoryChange;
457
+ $[5] = resolvedPlugins;
458
+ $[6] = styles;
459
+ $[7] = theme;
460
+ $[8] = t1;
461
+ } else t1 = $[8];
462
+ let t2;
463
+ if ($[9] !== active || $[10] !== document || $[11] !== endnotes || $[12] !== footnotes || $[13] !== onActiveChange || $[14] !== onDocumentChange || $[15] !== onStoryChange || $[16] !== resolvedPlugins || $[17] !== styles || $[18] !== theme) {
464
+ t2 = [
465
+ active,
466
+ document,
467
+ endnotes,
468
+ footnotes,
469
+ onActiveChange,
470
+ onDocumentChange,
471
+ onStoryChange,
472
+ resolvedPlugins,
473
+ styles,
474
+ theme
475
+ ];
476
+ $[9] = active;
477
+ $[10] = document;
478
+ $[11] = endnotes;
479
+ $[12] = footnotes;
480
+ $[13] = onActiveChange;
481
+ $[14] = onDocumentChange;
482
+ $[15] = onStoryChange;
483
+ $[16] = resolvedPlugins;
484
+ $[17] = styles;
485
+ $[18] = theme;
486
+ $[19] = t2;
487
+ } else t2 = $[19];
488
+ useEffect(t1, t2);
489
+ let t3;
490
+ let t4;
491
+ if ($[20] !== isSuggestionModeActive || $[21] !== suggestionAuthor) {
492
+ t3 = () => {
493
+ const manager_0 = managerRef.current;
494
+ if (!manager_0) return;
495
+ for (const story of manager_0.listStories()) {
496
+ const view_0 = manager_0.getView(story);
497
+ if (view_0) setSuggestionMode(isSuggestionModeActive, view_0.state, view_0.dispatch, suggestionAuthor);
498
+ }
499
+ };
500
+ t4 = [isSuggestionModeActive, suggestionAuthor];
501
+ $[20] = isSuggestionModeActive;
502
+ $[21] = suggestionAuthor;
503
+ $[22] = t3;
504
+ $[23] = t4;
505
+ } else {
506
+ t3 = $[22];
507
+ t4 = $[23];
508
+ }
509
+ useEffect(t3, t4);
510
+ let t5;
511
+ let t6;
512
+ if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
513
+ t5 = () => () => {
514
+ managerRef.current?.destroy();
515
+ };
516
+ t6 = [];
517
+ $[24] = t5;
518
+ $[25] = t6;
519
+ } else {
520
+ t5 = $[24];
521
+ t6 = $[25];
522
+ }
523
+ useEffect(t5, t6);
524
+ let t7;
525
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
526
+ t7 = () => {
527
+ managerRef.current?.activate(null);
528
+ setActive(null);
529
+ onActiveChangeRef.current(null);
530
+ };
531
+ $[26] = t7;
532
+ } else t7 = $[26];
533
+ const closeEditor = t7;
534
+ let t8;
535
+ if ($[27] !== isSuggestionModeActive || $[28] !== suggestionAuthor) {
536
+ t8 = () => ({
537
+ close: closeEditor,
538
+ getActiveView: () => {
539
+ const story_0 = managerRef.current?.getActive();
540
+ return story_0 ? managerRef.current?.getView(story_0) ?? null : null;
541
+ },
542
+ open: (story_1) => {
543
+ const view_1 = managerRef.current?.activate(story_1);
544
+ if (!view_1) return;
545
+ setSuggestionMode(isSuggestionModeActive, view_1.state, view_1.dispatch, suggestionAuthor);
546
+ setActive(story_1);
547
+ onActiveChangeRef.current(story_1);
548
+ requestAnimationFrame(() => view_1.focus());
549
+ },
550
+ snapshotDocument: (current_0) => managerRef.current?.snapshotDocument(current_0) ?? current_0
551
+ });
552
+ $[27] = isSuggestionModeActive;
553
+ $[28] = suggestionAuthor;
554
+ $[29] = t8;
555
+ } else t8 = $[29];
556
+ useImperativeHandle(ref, t8);
557
+ let t9;
558
+ if ($[30] !== active || $[31] !== t) {
559
+ t9 = active ? t(active.kind === "footnote" ? "dialogs.footnoteProperties.footnotes" : "dialogs.footnoteProperties.endnotes") : "";
560
+ $[30] = active;
561
+ $[31] = t;
562
+ $[32] = t9;
563
+ } else t9 = $[32];
564
+ const title = t9;
565
+ const t10 = active ? "block" : "none";
566
+ let t11;
567
+ if ($[33] !== t10) {
568
+ t11 = {
569
+ ...panelStyle,
570
+ display: t10
571
+ };
572
+ $[33] = t10;
573
+ $[34] = t11;
574
+ } else t11 = $[34];
575
+ let t12;
576
+ if ($[35] === Symbol.for("react.memo_cache_sentinel")) {
577
+ t12 = (event) => {
578
+ if (event.key !== "Escape") return;
579
+ event.preventDefault();
580
+ event.stopPropagation();
581
+ closeEditor();
582
+ };
583
+ $[35] = t12;
584
+ } else t12 = $[35];
585
+ let t13;
586
+ if ($[36] !== title) {
587
+ t13 = /* @__PURE__ */ jsx("span", { children: title });
588
+ $[36] = title;
589
+ $[37] = t13;
590
+ } else t13 = $[37];
591
+ let t14;
592
+ if ($[38] !== t) {
593
+ t14 = t("common.closeDialog");
594
+ $[38] = t;
595
+ $[39] = t14;
596
+ } else t14 = $[39];
597
+ let t15;
598
+ if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
599
+ t15 = {
600
+ border: 0,
601
+ background: "transparent",
602
+ color: "inherit",
603
+ cursor: "pointer"
604
+ };
605
+ $[40] = t15;
606
+ } else t15 = $[40];
607
+ let t16;
608
+ if ($[41] !== t14) {
609
+ t16 = /* @__PURE__ */ jsx("button", {
610
+ type: "button",
611
+ "aria-label": t14,
612
+ onClick: closeEditor,
613
+ style: t15,
614
+ children: "×"
615
+ });
616
+ $[41] = t14;
617
+ $[42] = t16;
618
+ } else t16 = $[42];
619
+ let t17;
620
+ if ($[43] !== t13 || $[44] !== t16) {
621
+ t17 = /* @__PURE__ */ jsxs("div", {
622
+ style: headerStyle,
623
+ children: [t13, t16]
624
+ });
625
+ $[43] = t13;
626
+ $[44] = t16;
627
+ $[45] = t17;
628
+ } else t17 = $[45];
629
+ let t18;
630
+ if ($[46] === Symbol.for("react.memo_cache_sentinel")) {
631
+ t18 = /* @__PURE__ */ jsx("div", {
632
+ ref: hostRef,
633
+ style: hostStyle
634
+ });
635
+ $[46] = t18;
636
+ } else t18 = $[46];
637
+ let t19;
638
+ if ($[47] !== t11 || $[48] !== t17 || $[49] !== title) {
639
+ t19 = /* @__PURE__ */ jsxs("aside", {
640
+ style: t11,
641
+ "aria-label": title,
642
+ onKeyDown: t12,
643
+ children: [t17, t18]
644
+ });
645
+ $[47] = t11;
646
+ $[48] = t17;
647
+ $[49] = title;
648
+ $[50] = t19;
649
+ } else t19 = $[50];
650
+ return t19;
651
+ });
652
+ NoteStoryEditor.displayName = "NoteStoryEditor";
653
+ //#endregion
478
654
  //#region src/utils/contained-handler.ts
479
655
  /**
480
656
  * Wrap a React event handler so it only fires when the event target
@@ -517,7 +693,7 @@ const containedHandler = (handler) => (event) => {
517
693
  };
518
694
  //#endregion
519
695
  //#region src/paged-editor/AISuggestionRectsOverlay.tsx
520
- const overlayStyles$5 = {
696
+ const overlayStyles$6 = {
521
697
  position: "absolute",
522
698
  top: 0,
523
699
  left: "50%",
@@ -539,14 +715,14 @@ const AISuggestionRectsOverlay = (t0) => {
539
715
  if (groups.length === 0) return null;
540
716
  let t1;
541
717
  if ($[0] !== groups) {
542
- t1 = groups.map(_temp$9);
718
+ t1 = groups.map(_temp$10);
543
719
  $[0] = groups;
544
720
  $[1] = t1;
545
721
  } else t1 = $[1];
546
722
  let t2;
547
723
  if ($[2] !== t1) {
548
724
  t2 = /* @__PURE__ */ jsx("div", {
549
- style: overlayStyles$5,
725
+ style: overlayStyles$6,
550
726
  "data-folio-ai-suggestions-overlay": "",
551
727
  children: t1
552
728
  });
@@ -555,7 +731,7 @@ const AISuggestionRectsOverlay = (t0) => {
555
731
  } else t2 = $[3];
556
732
  return t2;
557
733
  };
558
- function _temp$9(t0) {
734
+ function _temp$10(t0) {
559
735
  const { suggestion, rects, focused, font } = t0;
560
736
  const replacementAnchor = rects.at(-1);
561
737
  const showReplacement = focused && suggestion.suggestedText.length > 0 && replacementAnchor !== void 0;
@@ -616,7 +792,7 @@ function _temp$9(t0) {
616
792
  * `selectionSeq` changes — repeated clicks of the same
617
793
  * canonical in the sidebar re-trigger the scroll).
618
794
  */
619
- const overlayStyles$4 = {
795
+ const overlayStyles$5 = {
620
796
  position: "absolute",
621
797
  top: 0,
622
798
  left: "50%",
@@ -676,7 +852,7 @@ const AnonymizationRectsOverlay = ({ groups, onTermClick, selectedCanonical = nu
676
852
  if (groups.length === 0) return null;
677
853
  return /* @__PURE__ */ jsx("div", {
678
854
  ref: overlayRef,
679
- style: overlayStyles$4,
855
+ style: overlayStyles$5,
680
856
  "data-folio-anonymization-overlay": "",
681
857
  children: groups.flatMap((group) => {
682
858
  const isSelected = selectedCanonical === group.canonical;
@@ -706,7 +882,7 @@ const AnonymizationRectsOverlay = ({ groups, onTermClick, selectedCanonical = nu
706
882
  };
707
883
  //#endregion
708
884
  //#region src/paged-editor/AutocompleteCaretOverlay.tsx
709
- const overlayStyles$3 = {
885
+ const overlayStyles$4 = {
710
886
  position: "absolute",
711
887
  top: 0,
712
888
  left: "50%",
@@ -757,7 +933,7 @@ const AutocompleteCaretOverlay = (t0) => {
757
933
  let t6;
758
934
  if ($[9] !== t3 || $[10] !== t5 || $[11] !== text) {
759
935
  t6 = /* @__PURE__ */ jsx("div", {
760
- style: overlayStyles$3,
936
+ style: overlayStyles$4,
761
937
  "data-folio-autocomplete-overlay": "",
762
938
  children: /* @__PURE__ */ jsxs("span", {
763
939
  className: "folio-autocomplete-ghost",
@@ -773,6 +949,52 @@ const AutocompleteCaretOverlay = (t0) => {
773
949
  return t6;
774
950
  };
775
951
  //#endregion
952
+ //#region src/paged-editor/PassageHighlightOverlay.tsx
953
+ const overlayStyles$3 = {
954
+ position: "absolute",
955
+ top: 0,
956
+ left: "50%",
957
+ width: "100vw",
958
+ height: "100%",
959
+ transform: "translateX(-50%)",
960
+ pointerEvents: "none",
961
+ zIndex: 1
962
+ };
963
+ const PassageHighlightOverlay = (t0) => {
964
+ const $ = c(4);
965
+ const { rects } = t0;
966
+ if (rects.length === 0) return null;
967
+ let t1;
968
+ if ($[0] !== rects) {
969
+ t1 = rects.map(_temp$9);
970
+ $[0] = rects;
971
+ $[1] = t1;
972
+ } else t1 = $[1];
973
+ let t2;
974
+ if ($[2] !== t1) {
975
+ t2 = /* @__PURE__ */ jsx("div", {
976
+ style: overlayStyles$3,
977
+ "data-folio-passage-highlight-overlay": "",
978
+ children: t1
979
+ });
980
+ $[2] = t1;
981
+ $[3] = t2;
982
+ } else t2 = $[3];
983
+ return t2;
984
+ };
985
+ function _temp$9(rect, idx) {
986
+ return /* @__PURE__ */ jsx("span", {
987
+ className: "folio-passage-highlight",
988
+ style: {
989
+ position: "absolute",
990
+ left: rect.x,
991
+ top: rect.y,
992
+ width: rect.width,
993
+ height: rect.height
994
+ }
995
+ }, `${idx}:${rect.pageIndex}:${rect.x}:${rect.y}`);
996
+ }
997
+ //#endregion
776
998
  //#region src/paged-editor/embeddedFonts.ts
777
999
  /**
778
1000
  * Registers a document's embedded fonts with the browser via the `FontFace`
@@ -878,6 +1100,7 @@ function toFontFaceInputs(fonts) {
878
1100
  if (!isValidFontDefinition(font)) continue;
879
1101
  const descriptors = { display: "swap" };
880
1102
  if (typeof font.weight === "number" || typeof font.weight === "string") descriptors.weight = String(font.weight);
1103
+ if (isNonEmptyString$1(font.style)) descriptors.style = font.style.trim();
881
1104
  inputs.push({
882
1105
  family: font.family.trim(),
883
1106
  source: `url(${JSON.stringify(font.src.trim())})`,
@@ -923,17 +1146,6 @@ async function loadHostFontFaces(fonts) {
923
1146
  * so that ProseMirror's internal measurements stay valid.
924
1147
  */
925
1148
  const EMPTY_EXTERNAL_PLUGINS = [];
926
- let collaborationModulesPromise = null;
927
- const loadCollaborationModules = () => {
928
- collaborationModulesPromise ??= Promise.all([import("y-prosemirror"), import("yjs")]).then(([yProseMirror, yjs]) => ({
929
- yProseMirror,
930
- yjs
931
- })).catch((error) => {
932
- collaborationModulesPromise = null;
933
- throw error;
934
- });
935
- return collaborationModulesPromise;
936
- };
937
1149
  /**
938
1150
  * Hidden wrapper styles - visually hidden, focus-safe scroll isolation.
939
1151
  *
@@ -968,7 +1180,7 @@ const HIDDEN_HOST_STYLES = {
968
1180
  * HiddenProseMirror - Off-screen ProseMirror editor for keyboard input
969
1181
  */
970
1182
  const HiddenProseMirror = forwardRef((props, ref) => {
971
- 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;
1183
+ 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;
972
1184
  const [collaborationModules, setCollaborationModules] = useState(null);
973
1185
  const [collaborationModulesError, setCollaborationModulesError] = useState(null);
974
1186
  const hasCollaboration = collaboration !== void 0;
@@ -987,6 +1199,9 @@ const HiddenProseMirror = forwardRef((props, ref) => {
987
1199
  const onEditorViewReadyRef = useRef(onEditorViewReady);
988
1200
  const onEditorViewDestroyRef = useRef(onEditorViewDestroy);
989
1201
  const onKeyDownRef = useRef(onKeyDown);
1202
+ const onCopyRef = useRef(onCopy);
1203
+ const onCutRef = useRef(onCut);
1204
+ const onPasteRef = useRef(onPaste);
990
1205
  const onReadOnlyEditAttemptRef = useRef(onReadOnlyEditAttempt);
991
1206
  const onRemoteSelectionsChangeRef = useRef(onRemoteSelectionsChange);
992
1207
  readOnlyRef.current = readOnly;
@@ -999,6 +1214,9 @@ const HiddenProseMirror = forwardRef((props, ref) => {
999
1214
  onEditorViewReadyRef.current = onEditorViewReady;
1000
1215
  onEditorViewDestroyRef.current = onEditorViewDestroy;
1001
1216
  onKeyDownRef.current = onKeyDown;
1217
+ onCopyRef.current = onCopy;
1218
+ onCutRef.current = onCut;
1219
+ onPasteRef.current = onPaste;
1002
1220
  onReadOnlyEditAttemptRef.current = onReadOnlyEditAttempt;
1003
1221
  onRemoteSelectionsChangeRef.current = onRemoteSelectionsChange;
1004
1222
  collaborationRef.current = collaboration;
@@ -1021,6 +1239,9 @@ const HiddenProseMirror = forwardRef((props, ref) => {
1021
1239
  onTransaction: (transaction, newState) => onTransactionRef.current?.(transaction, newState),
1022
1240
  onSelectionChange: (state) => onSelectionChangeRef.current?.(state),
1023
1241
  onKeyDown: (view, event) => onKeyDownRef.current?.(view, event) ?? false,
1242
+ onCopy: () => onCopyRef.current?.(),
1243
+ onCut: () => onCutRef.current?.(),
1244
+ onPaste: () => onPasteRef.current?.(),
1024
1245
  onReadOnlyEditAttempt: () => onReadOnlyEditAttemptRef.current?.(),
1025
1246
  onEditorViewReady: (view_0) => onEditorViewReadyRef.current?.(view_0),
1026
1247
  onEditorViewDestroy: () => onEditorViewDestroyRef.current?.(),
@@ -2822,6 +3043,7 @@ function buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, doc) {
2822
3043
  const text = getFootnoteText(fn);
2823
3044
  items.push({
2824
3045
  displayNumber: String(displayNum),
3046
+ noteId: fnId,
2825
3047
  text,
2826
3048
  ...content ? { content: {
2827
3049
  blocks: content.blocks,
@@ -2838,7 +3060,7 @@ function buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, doc) {
2838
3060
  * PagedEditor - Main paginated editing component.
2839
3061
  */
2840
3062
  const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2841
- 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;
3063
+ 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;
2842
3064
  const getScrollContainer = useCallback(() => {
2843
3065
  if (scrollContainerRefProp && typeof scrollContainerRefProp === "object") return scrollContainerRefProp.current;
2844
3066
  return containerRef.current;
@@ -2848,7 +3070,17 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2848
3070
  const folioEmitterRef = useRef(createFolioEditorEmitter());
2849
3071
  const hiddenPMRef = useRef(null);
2850
3072
  const hfPMsRef = useRef(null);
3073
+ const noteEditorRef = useRef(null);
3074
+ const [noteStoryActive, setNoteStoryActive] = useState(false);
2851
3075
  const painterRef = useRef(null);
3076
+ const noteStoryPlugins = useMemo(() => externalPlugins.filter(({ spec }) => spec.key === suggestionModeKey), [externalPlugins]);
3077
+ const handleActiveNoteStoryChange = useCallback((story) => {
3078
+ setNoteStoryActive(story !== null);
3079
+ onActiveNoteStoryChange?.(story);
3080
+ }, [onActiveNoteStoryChange]);
3081
+ useEffect(() => {
3082
+ if (readOnly) noteEditorRef.current?.close();
3083
+ }, [readOnly]);
2852
3084
  const { handlePMKeyDown } = useVisualLineNavigation({ pagesContainerRef });
2853
3085
  const handleHiddenEditorKeyDown = useCallback((view, event) => {
2854
3086
  if (getTemplateSlashMenu(view.state).active) return false;
@@ -2913,6 +3145,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
2913
3145
  focusedId: null
2914
3146
  });
2915
3147
  const [aiSuggestionsOverlayRequestGate] = useState(createLatestRequestGate);
3148
+ const passageHighlightRangeRef = useRef(null);
3149
+ const [passageHighlightRects, setPassageHighlightRects] = useState([]);
3150
+ const [passageHighlightOverlayRequestGate] = useState(createLatestRequestGate);
2916
3151
  const [remoteSelections, setRemoteSelections] = useState([]);
2917
3152
  const suppressSelectionOverlayRef = useRef(false);
2918
3153
  const revealSelectionOverlayTimerRef = useRef(null);
@@ -3099,6 +3334,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3099
3334
  pageSize,
3100
3335
  margins,
3101
3336
  pageGap,
3337
+ showMarginGuides,
3338
+ marginGuideColor,
3102
3339
  syncCoordinator,
3103
3340
  headerContent,
3104
3341
  footerContent,
@@ -3142,6 +3379,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3142
3379
  margins,
3143
3380
  pageGap,
3144
3381
  zoom,
3382
+ showMarginGuides,
3383
+ marginGuideColor,
3145
3384
  syncCoordinator,
3146
3385
  headerContent,
3147
3386
  footerContent,
@@ -3169,6 +3408,27 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3169
3408
  emitter: folioEmitterRef.current
3170
3409
  });
3171
3410
  const folioEditor = folioEditorRef.current;
3411
+ const getActiveEditorStory = useCallback(() => resolveActiveEditorStory({
3412
+ bodyView: folioEditor.getView(),
3413
+ headerFooterView: hfEditMode && activeHeaderFooterRId ? hfPMsRef.current?.getView(activeHeaderFooterRId) ?? null : null,
3414
+ noteView: noteEditorRef.current?.getActiveView() ?? null
3415
+ }), [
3416
+ activeHeaderFooterRId,
3417
+ folioEditor,
3418
+ hfEditMode
3419
+ ]);
3420
+ const marginGuideSettingsInitializedRef = useRef(false);
3421
+ useEffect(() => {
3422
+ if (!marginGuideSettingsInitializedRef.current) {
3423
+ marginGuideSettingsInitializedRef.current = true;
3424
+ return;
3425
+ }
3426
+ folioEditor.relayout();
3427
+ }, [
3428
+ folioEditor,
3429
+ marginGuideColor,
3430
+ showMarginGuides
3431
+ ]);
3172
3432
  const layoutSchedulerRef = useRef(null);
3173
3433
  if (layoutSchedulerRef.current === null) layoutSchedulerRef.current = createLayoutScheduler({
3174
3434
  runLayout: (state_1, options_1) => runLayoutPipelineRef.current(state_1, options_1),
@@ -3656,6 +3916,41 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3656
3916
  measures,
3657
3917
  zoom
3658
3918
  ]);
3919
+ const updatePassageHighlightOverlay = useCallback(() => {
3920
+ const isCurrentRequest_4 = passageHighlightOverlayRequestGate.begin();
3921
+ const range_5 = passageHighlightRangeRef.current;
3922
+ const pagesContainer_3 = pagesContainerRef.current;
3923
+ if (range_5 === null || !pagesContainer_3) {
3924
+ setPassageHighlightRects((prev_0) => prev_0.length === 0 ? prev_0 : []);
3925
+ return;
3926
+ }
3927
+ (async () => {
3928
+ const projected_1 = await projectRangesToRects([range_5], {
3929
+ pagesContainer: pagesContainer_3,
3930
+ zoom,
3931
+ layout,
3932
+ blocks,
3933
+ measures
3934
+ });
3935
+ if (!isCurrentRequest_4()) return;
3936
+ setPassageHighlightRects(projected_1.at(0)?.rects ?? []);
3937
+ })();
3938
+ }, [
3939
+ passageHighlightOverlayRequestGate,
3940
+ layout,
3941
+ blocks,
3942
+ measures,
3943
+ zoom
3944
+ ]);
3945
+ const setPassageHighlightImpl = useCallback((range_6) => {
3946
+ passageHighlightRangeRef.current = range_6;
3947
+ if (range_6 === null) {
3948
+ passageHighlightOverlayRequestGate.invalidate();
3949
+ setPassageHighlightRects((prev_1) => prev_1.length === 0 ? prev_1 : []);
3950
+ return;
3951
+ }
3952
+ updatePassageHighlightOverlay();
3953
+ }, [passageHighlightOverlayRequestGate, updatePassageHighlightOverlay]);
3659
3954
  const hideSelectionOverlayDuringInput = useCallback((state_4) => {
3660
3955
  selectionOverlayRequestGate.invalidate();
3661
3956
  suppressSelectionOverlayRef.current = true;
@@ -3674,6 +3969,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3674
3969
  autocompleteOverlayRequestGate.invalidate();
3675
3970
  directivesOverlayRequestGate.invalidate();
3676
3971
  aiSuggestionsOverlayRequestGate.invalidate();
3972
+ passageHighlightOverlayRequestGate.invalidate();
3677
3973
  if (revealSelectionOverlayTimerRef.current !== null) {
3678
3974
  window.clearTimeout(revealSelectionOverlayTimerRef.current);
3679
3975
  revealSelectionOverlayTimerRef.current = null;
@@ -3683,6 +3979,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3683
3979
  anonymizationOverlayRequestGate,
3684
3980
  autocompleteOverlayRequestGate,
3685
3981
  directivesOverlayRequestGate,
3982
+ passageHighlightOverlayRequestGate,
3686
3983
  selectionOverlayRequestGate
3687
3984
  ]);
3688
3985
  /**
@@ -3730,6 +4027,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3730
4027
  }
3731
4028
  if (transaction.docChanged) {
3732
4029
  syncCoordinator.incrementStateSeq();
4030
+ if (passageHighlightRangeRef.current !== null) {
4031
+ passageHighlightRangeRef.current = null;
4032
+ passageHighlightOverlayRequestGate.invalidate();
4033
+ setPassageHighlightRects((prev_2) => prev_2.length === 0 ? prev_2 : []);
4034
+ }
3733
4035
  hideSelectionOverlayDuringInput(newState);
3734
4036
  scheduleLayout(newState, getTransactionDirtyRange(transaction));
3735
4037
  scheduleDocumentChangeNotification();
@@ -3745,6 +4047,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3745
4047
  updateAutocompleteOverlay,
3746
4048
  updateDirectivesOverlay,
3747
4049
  updateAISuggestionsOverlay,
4050
+ passageHighlightOverlayRequestGate,
3748
4051
  syncCoordinator
3749
4052
  ]);
3750
4053
  /**
@@ -3791,6 +4094,24 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3791
4094
  });
3792
4095
  }
3793
4096
  }, [scheduleLayout, ensureHiddenEditorView]);
4097
+ const handleNoteStoryTransaction = useCallback((view_2, docChanged_0, selectionChanged_0) => {
4098
+ if (docChanged_0) {
4099
+ const bodyState_0 = hiddenPMRef.current?.getState();
4100
+ if (bodyState_0) scheduleLayout(bodyState_0, null);
4101
+ }
4102
+ if (docChanged_0 || selectionChanged_0) {
4103
+ const { from: from_2, to: to_2 } = view_2.state.selection;
4104
+ onSelectionChangeRef.current?.(from_2, to_2);
4105
+ folioEmitterRef.current.emit("selectionChange", {
4106
+ from: from_2,
4107
+ to: to_2
4108
+ });
4109
+ }
4110
+ }, [scheduleLayout]);
4111
+ const handleNoteDocumentChange = useCallback((updated) => {
4112
+ onDocumentChangeRef.current?.(updated);
4113
+ folioEmitterRef.current.emit("docChange", updated);
4114
+ }, []);
3794
4115
  useEffect(() => {
3795
4116
  if (!hfEditMode) setHfCaretSelection(null);
3796
4117
  dragAnchorRef.current = null;
@@ -3807,12 +4128,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3807
4128
  setCaretPosition(null);
3808
4129
  } else if (syncCoordinator.isSafeToRender()) updateSelectionOverlay(state_5);
3809
4130
  requestAnimationFrame(() => {
3810
- const view_2 = hiddenPMRef.current?.getView();
3811
- if (!view_2) {
4131
+ const view_3 = hiddenPMRef.current?.getView();
4132
+ if (!view_3) {
3812
4133
  setSelectedImageInfo(null);
3813
4134
  return;
3814
4135
  }
3815
- const { selection: sel_0 } = view_2.state;
4136
+ const { selection: sel_0 } = view_3.state;
3816
4137
  if (sel_0 instanceof NodeSelection && sel_0.node.type.name === "image") {
3817
4138
  const pmPos_2 = sel_0.from;
3818
4139
  const imgEl = pagesContainerRef.current ? findBodyPmAnchor(pagesContainerRef.current, pmPos_2) : null;
@@ -3888,9 +4209,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3888
4209
  return null;
3889
4210
  }, []);
3890
4211
  const findCellPosFromPmPos = useCallback((pmPos_4) => {
3891
- const view_3 = hiddenPMRef.current?.getView();
3892
- if (!view_3) return null;
3893
- return findCellPosInDoc(view_3.state.doc, pmPos_4);
4212
+ const view_4 = hiddenPMRef.current?.getView();
4213
+ if (!view_4) return null;
4214
+ return findCellPosInDoc(view_4.state.doc, pmPos_4);
3894
4215
  }, [findCellPosInDoc]);
3895
4216
  /**
3896
4217
  * Find the closest image element from a click target.
@@ -3978,10 +4299,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
3978
4299
  cellDragAnchorPosRef.current = null;
3979
4300
  cellDragContentEndRef.current = null;
3980
4301
  isCellDraggingRef.current = false;
3981
- const view_4 = hiddenPMRef.current?.getView();
4302
+ const view_5 = hiddenPMRef.current?.getView();
3982
4303
  let endPos;
3983
- if (view_4) {
3984
- endPos = Math.max(0, view_4.state.doc.content.size - 1);
4304
+ if (view_5) {
4305
+ endPos = Math.max(0, view_5.state.doc.content.size - 1);
3985
4306
  hiddenPMRef.current?.setSelection(endPos);
3986
4307
  } else {
3987
4308
  endPos = Math.max(0, (precomputedInitialStateRef.current?.doc.content.size ?? 1) - 1);
@@ -4001,11 +4322,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4001
4322
  queueHiddenEditorSelection
4002
4323
  ]);
4003
4324
  const copySelectionText = useCallback(() => {
4004
- const view_5 = hiddenPMRef.current?.getView();
4005
- if (!view_5) return false;
4006
- const { from: from_2, to: to_2 } = view_5.state.selection;
4007
- if (from_2 === to_2) return false;
4008
- const text_1 = view_5.state.doc.textBetween(from_2, to_2, "\n");
4325
+ const view_6 = hiddenPMRef.current?.getView();
4326
+ if (!view_6) return false;
4327
+ const { from: from_3, to: to_3 } = view_6.state.selection;
4328
+ if (from_3 === to_3) return false;
4329
+ const text_1 = view_6.state.doc.textBetween(from_3, to_3, "\n");
4009
4330
  if (!text_1) return false;
4010
4331
  if (navigator.clipboard === void 0) return false;
4011
4332
  navigator.clipboard.writeText(text_1).catch(() => void 0);
@@ -4025,6 +4346,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4025
4346
  clearTableInsertTimer();
4026
4347
  const target_1 = e.target instanceof HTMLElement ? e.target : null;
4027
4348
  if (!target_1) return;
4349
+ noteEditorRef.current?.close();
4028
4350
  const anchorClosest = target_1.closest("a[href]");
4029
4351
  if (anchorClosest instanceof HTMLAnchorElement ? anchorClosest : null) e.preventDefault();
4030
4352
  if (!readOnly && hfEditMode && onBodyClick) {
@@ -4098,9 +4420,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4098
4420
  const colIndex = Number.parseInt(target_1.dataset["columnIndex"] ?? "0", 10);
4099
4421
  resizeColumnIndexRef.current = colIndex;
4100
4422
  resizeTablePmStartRef.current = Number.parseInt(target_1.dataset["tablePmStart"] ?? "0", 10);
4101
- const view_6 = resizeViewForRead;
4102
- if (view_6) {
4103
- const $pos_1 = view_6.state.doc.resolve(resizeTablePmStartRef.current + 1);
4423
+ const view_7 = resizeViewForRead;
4424
+ if (view_7) {
4425
+ const $pos_1 = view_7.state.doc.resolve(resizeTablePmStartRef.current + 1);
4104
4426
  for (let d_0 = $pos_1.depth; d_0 >= 0; d_0--) {
4105
4427
  const node_1 = $pos_1.node(d_0);
4106
4428
  if (node_1.type.name === "table") {
@@ -4130,9 +4452,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4130
4452
  const rowIndex = Number.parseInt(target_1.dataset["rowIndex"] ?? "0", 10);
4131
4453
  resizeRowIndexRef.current = rowIndex;
4132
4454
  resizeRowTablePmStartRef.current = Number.parseInt(target_1.dataset["tablePmStart"] ?? "0", 10);
4133
- const view_7 = resizeViewForRead;
4134
- if (view_7) {
4135
- const $pos_2 = view_7.state.doc.resolve(resizeRowTablePmStartRef.current + 1);
4455
+ const view_8 = resizeViewForRead;
4456
+ if (view_8) {
4457
+ const $pos_2 = view_8.state.doc.resolve(resizeRowTablePmStartRef.current + 1);
4136
4458
  for (let d_1 = $pos_2.depth; d_1 >= 0; d_1--) {
4137
4459
  const node_2 = $pos_2.node(d_1);
4138
4460
  if (node_2.type.name === "table") {
@@ -4165,9 +4487,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4165
4487
  const colIndex_0 = Number.parseInt(target_1.dataset["columnIndex"] ?? "0", 10);
4166
4488
  resizeRightEdgeColIndexRef.current = colIndex_0;
4167
4489
  resizeRightEdgePmStartRef.current = Number.parseInt(target_1.dataset["tablePmStart"] ?? "0", 10);
4168
- const view_8 = resizeViewForRead;
4169
- if (view_8) {
4170
- const $pos_3 = view_8.state.doc.resolve(resizeRightEdgePmStartRef.current + 1);
4490
+ const view_9 = resizeViewForRead;
4491
+ if (view_9) {
4492
+ const $pos_3 = view_9.state.doc.resolve(resizeRightEdgePmStartRef.current + 1);
4171
4493
  for (let d_2 = $pos_3.depth; d_2 >= 0; d_2--) {
4172
4494
  const node_3 = $pos_3.node(d_2);
4173
4495
  if (node_3.type.name === "table") {
@@ -4366,18 +4688,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4366
4688
  resizeHandleRef.current.classList.remove("dragging");
4367
4689
  resizeHandleRef.current = null;
4368
4690
  }
4369
- const view_9 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4691
+ const view_10 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4370
4692
  resizingHfSurfaceRef.current = null;
4371
- if (view_9) {
4693
+ if (view_10) {
4372
4694
  const pmStart_4 = resizeTablePmStartRef.current;
4373
4695
  const colIdx = resizeColumnIndexRef.current;
4374
4696
  const { left: newLeft, right: newRight } = resizeOrigWidthsRef.current;
4375
- const $pos_5 = view_9.state.doc.resolve(pmStart_4 + 1);
4697
+ const $pos_5 = view_10.state.doc.resolve(pmStart_4 + 1);
4376
4698
  for (let d_3 = $pos_5.depth; d_3 >= 0; d_3--) {
4377
4699
  const node_4 = $pos_5.node(d_3);
4378
4700
  if (node_4.type.name === "table") {
4379
4701
  const tablePos = $pos_5.before(d_3);
4380
- const tr = view_9.state.tr;
4702
+ const tr = view_10.state.tr;
4381
4703
  const tableAttrs = expectTableAttrs(node_4);
4382
4704
  if (!tableAttrs.columnWidths) break;
4383
4705
  const widths_1 = [...tableAttrs.columnWidths];
@@ -4403,7 +4725,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4403
4725
  });
4404
4726
  rowOffset += row.nodeSize;
4405
4727
  });
4406
- view_9.dispatch(tr);
4728
+ view_10.dispatch(tr);
4407
4729
  break;
4408
4730
  }
4409
4731
  }
@@ -4416,18 +4738,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4416
4738
  resizeRowHandleRef.current.classList.remove("dragging");
4417
4739
  resizeRowHandleRef.current = null;
4418
4740
  }
4419
- const view_10 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4741
+ const view_11 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4420
4742
  resizingHfSurfaceRef.current = null;
4421
- if (view_10) {
4743
+ if (view_11) {
4422
4744
  const pmStart_5 = resizeRowTablePmStartRef.current;
4423
4745
  const rowIdx = resizeRowIndexRef.current;
4424
4746
  const newHeight_0 = resizeRowOrigHeightRef.current;
4425
- const $pos_6 = view_10.state.doc.resolve(pmStart_5 + 1);
4747
+ const $pos_6 = view_11.state.doc.resolve(pmStart_5 + 1);
4426
4748
  for (let d_4 = $pos_6.depth; d_4 >= 0; d_4--) {
4427
4749
  const node_5 = $pos_6.node(d_4);
4428
4750
  if (node_5.type.name === "table") {
4429
4751
  const tablePos_0 = $pos_6.before(d_4);
4430
- const tr_0 = view_10.state.tr;
4752
+ const tr_0 = view_11.state.tr;
4431
4753
  let rowOffset_0 = tablePos_0 + 1;
4432
4754
  let idx = 0;
4433
4755
  node_5.forEach((row_0) => {
@@ -4438,7 +4760,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4438
4760
  rowOffset_0 += row_0.nodeSize;
4439
4761
  idx++;
4440
4762
  });
4441
- view_10.dispatch(tr_0);
4763
+ view_11.dispatch(tr_0);
4442
4764
  break;
4443
4765
  }
4444
4766
  }
@@ -4451,18 +4773,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4451
4773
  resizeRightEdgeHandleRef.current.classList.remove("dragging");
4452
4774
  resizeRightEdgeHandleRef.current = null;
4453
4775
  }
4454
- const view_11 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4776
+ const view_12 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
4455
4777
  resizingHfSurfaceRef.current = null;
4456
- if (view_11) {
4778
+ if (view_12) {
4457
4779
  const pmStart_6 = resizeRightEdgePmStartRef.current;
4458
4780
  const colIdx_0 = resizeRightEdgeColIndexRef.current;
4459
4781
  const newWidth_1 = resizeRightEdgeOrigWidthRef.current;
4460
- const $pos_7 = view_11.state.doc.resolve(pmStart_6 + 1);
4782
+ const $pos_7 = view_12.state.doc.resolve(pmStart_6 + 1);
4461
4783
  for (let d_5 = $pos_7.depth; d_5 >= 0; d_5--) {
4462
4784
  const node_6 = $pos_7.node(d_5);
4463
4785
  if (node_6.type.name === "table") {
4464
4786
  const tablePos_1 = $pos_7.before(d_5);
4465
- const tr_1 = view_11.state.tr;
4787
+ const tr_1 = view_12.state.tr;
4466
4788
  const tableAttrs_0 = expectTableAttrs(node_6);
4467
4789
  if (!tableAttrs_0.columnWidths) break;
4468
4790
  const widths_2 = [...tableAttrs_0.columnWidths];
@@ -4484,7 +4806,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4484
4806
  });
4485
4807
  rowOffset_1 += row_1.nodeSize;
4486
4808
  });
4487
- view_11.dispatch(tr_1);
4809
+ view_12.dispatch(tr_1);
4488
4810
  break;
4489
4811
  }
4490
4812
  }
@@ -4626,13 +4948,13 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4626
4948
  e_2.preventDefault();
4627
4949
  e_2.stopPropagation();
4628
4950
  if (!tableInsertButton || !hiddenPMRef.current) return;
4629
- const view_12 = hiddenPMRef.current.getView();
4630
- if (!view_12) return;
4951
+ const view_13 = hiddenPMRef.current.getView();
4952
+ if (!view_13) return;
4631
4953
  const { type, cellPmPos } = tableInsertButton;
4632
- const tr_2 = view_12.state.tr.setSelection(TextSelection$1.create(view_12.state.doc, cellPmPos + 1));
4633
- view_12.dispatch(tr_2);
4634
- if (type === "row") addRowBelow(view_12.state, view_12.dispatch);
4635
- else addColumnRight(view_12.state, view_12.dispatch);
4954
+ const tr_2 = view_13.state.tr.setSelection(TextSelection$1.create(view_13.state.doc, cellPmPos + 1));
4955
+ view_13.dispatch(tr_2);
4956
+ if (type === "row") addRowBelow(view_13.state, view_13.dispatch);
4957
+ else addColumnRight(view_13.state, view_13.dispatch);
4636
4958
  setTableInsertButton(null);
4637
4959
  hiddenPMRef.current.focus();
4638
4960
  }, [tableInsertButton]);
@@ -4642,6 +4964,15 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4642
4964
  const handlePagesClick = useCallback((e_3) => {
4643
4965
  const target_2 = e_3.target instanceof HTMLElement ? e_3.target : null;
4644
4966
  if (!target_2) return;
4967
+ if (!readOnly && e_3.detail === 2) {
4968
+ const story_0 = findNoteStoryForTarget(target_2);
4969
+ if (story_0) {
4970
+ e_3.preventDefault();
4971
+ e_3.stopPropagation();
4972
+ noteEditorRef.current?.open(story_0);
4973
+ return;
4974
+ }
4975
+ }
4645
4976
  const anchorClosest_0 = target_2.closest("a[href]");
4646
4977
  const anchorEl_0 = anchorClosest_0 instanceof HTMLAnchorElement ? anchorClosest_0 : null;
4647
4978
  if (anchorEl_0) {
@@ -4650,10 +4981,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4650
4981
  if (href.startsWith("#")) {
4651
4982
  const bookmarkName = href.slice(1);
4652
4983
  if (bookmarkName && hiddenPMRef.current) {
4653
- const view_13 = hiddenPMRef.current.getView();
4654
- if (view_13) {
4984
+ const view_14 = hiddenPMRef.current.getView();
4985
+ if (view_14) {
4655
4986
  const targetPos = { value: null };
4656
- view_13.state.doc.descendants((node_7, pos_2) => {
4987
+ view_14.state.doc.descendants((node_7, pos_2) => {
4657
4988
  if (targetPos.value !== null) return false;
4658
4989
  if (node_7.type.name === "paragraph") {
4659
4990
  if (node_7.attrs["bookmarks"]?.some((b) => b.name === bookmarkName)) {
@@ -4742,9 +5073,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4742
5073
  if (e_3.detail === 2 && hiddenPMRef.current) {
4743
5074
  const pmPos_12 = getPositionFromMouse(e_3.clientX, e_3.clientY);
4744
5075
  if (pmPos_12 !== null) {
4745
- const view_14 = hiddenPMRef.current.getView();
4746
- if (view_14) {
4747
- const { doc: doc_0 } = view_14.state;
5076
+ const view_15 = hiddenPMRef.current.getView();
5077
+ if (view_15) {
5078
+ const { doc: doc_0 } = view_15.state;
4748
5079
  const $pos_9 = doc_0.resolve(pmPos_12);
4749
5080
  const parent_0 = $pos_9.parent;
4750
5081
  if (parent_0.isTextblock) {
@@ -4770,9 +5101,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4770
5101
  if (e_3.detail === 3 && hiddenPMRef.current) {
4771
5102
  const pmPos_13 = getPositionFromMouse(e_3.clientX, e_3.clientY);
4772
5103
  if (pmPos_13 !== null) {
4773
- const view_15 = hiddenPMRef.current.getView();
4774
- if (view_15) {
4775
- const { doc: doc_1 } = view_15.state;
5104
+ const view_16 = hiddenPMRef.current.getView();
5105
+ if (view_16) {
5106
+ const { doc: doc_1 } = view_16.state;
4776
5107
  const $pos_10 = doc_1.resolve(pmPos_13);
4777
5108
  const paragraphStart = $pos_10.start($pos_10.depth);
4778
5109
  const paragraphEnd = $pos_10.end($pos_10.depth);
@@ -4798,9 +5129,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4798
5129
  if (slot_2) {
4799
5130
  const hfView_4 = hfPMsRef.current?.getView(slot_2.rId);
4800
5131
  if (hfView_4) {
4801
- const { from: from_3, to: to_3 } = hfView_4.state.selection;
5132
+ const { from: from_4, to: to_4 } = hfView_4.state.selection;
4802
5133
  const pmPos_14 = clickToPositionInHfSlot(pagesContainerRef.current ?? slot_2.element, slot_2.kind, slot_2.rId, e_4.clientX, e_4.clientY);
4803
- if (pmPos_14 !== null && (from_3 === to_3 || pmPos_14 < from_3 || pmPos_14 > to_3)) {
5134
+ if (pmPos_14 !== null && (from_4 === to_4 || pmPos_14 < from_4 || pmPos_14 > to_4)) {
4804
5135
  const docEnd_3 = hfView_4.state.doc.content.size;
4805
5136
  const clamped_1 = Math.max(0, Math.min(pmPos_14, docEnd_3));
4806
5137
  const $pos_11 = hfView_4.state.doc.resolve(clamped_1);
@@ -4817,11 +5148,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4817
5148
  }
4818
5149
  }
4819
5150
  }
4820
- const view_16 = hiddenPMRef.current?.getView();
4821
- if (!view_16) return;
4822
- const { from: from_4, to: to_4 } = view_16.state.selection;
5151
+ const view_17 = hiddenPMRef.current?.getView();
5152
+ if (!view_17) return;
5153
+ const { from: from_5, to: to_5 } = view_17.state.selection;
4823
5154
  const pmPos_15 = getPositionFromMouse(e_4.clientX, e_4.clientY);
4824
- if (pmPos_15 !== null && (from_4 === to_4 || pmPos_15 < from_4 || pmPos_15 > to_4)) {
5155
+ if (pmPos_15 !== null && (from_5 === to_5 || pmPos_15 < from_5 || pmPos_15 > to_5)) {
4825
5156
  hiddenPMRef.current?.setSelection(pmPos_15);
4826
5157
  hiddenPMRef.current?.focus();
4827
5158
  setIsFocused(true);
@@ -4844,7 +5175,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4844
5175
  */
4845
5176
  const handleContainerFocus = useCallback((e_5) => {
4846
5177
  if (e_5.target instanceof HTMLElement && e_5.target.closest(".docx-comments-sidebar")) return;
4847
- if (e_5.target instanceof HTMLElement && e_5.target.closest("[data-hf-r-id]")) return;
5178
+ if (e_5.target instanceof HTMLElement && e_5.target.closest("[data-hf-r-id], [data-note-kind][data-note-id]")) return;
4848
5179
  focusHiddenEditor();
4849
5180
  }, [focusHiddenEditor]);
4850
5181
  /**
@@ -4860,16 +5191,16 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4860
5191
  * Handle image resize from the overlay.
4861
5192
  */
4862
5193
  const handleImageResize = useCallback((pmPos_16, newWidth_2, newHeight_1) => {
4863
- const view_17 = hiddenPMRef.current?.getView();
4864
- if (!view_17) return;
5194
+ const view_18 = hiddenPMRef.current?.getView();
5195
+ if (!view_18) return;
4865
5196
  try {
4866
- const node_10 = view_17.state.doc.nodeAt(pmPos_16);
5197
+ const node_10 = view_18.state.doc.nodeAt(pmPos_16);
4867
5198
  if (!node_10 || node_10.type.name !== "image") return;
4868
- const tr_3 = view_17.state.tr.setNodeMarkup(pmPos_16, void 0, mergeImageAttrs(node_10, {
5199
+ const tr_3 = view_18.state.tr.setNodeMarkup(pmPos_16, void 0, mergeImageAttrs(node_10, {
4869
5200
  width: newWidth_2,
4870
5201
  height: newHeight_1
4871
5202
  }));
4872
- view_17.dispatch(tr_3);
5203
+ view_18.dispatch(tr_3);
4873
5204
  hiddenPMRef.current?.setNodeSelection(pmPos_16);
4874
5205
  } catch {}
4875
5206
  }, []);
@@ -4890,10 +5221,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4890
5221
  * to the drop position determined by mouse coordinates.
4891
5222
  */
4892
5223
  const handleImageDragMove = useCallback((pmPos_17, clientX_1, clientY_1) => {
4893
- const view_18 = hiddenPMRef.current?.getView();
4894
- if (!view_18) return;
5224
+ const view_19 = hiddenPMRef.current?.getView();
5225
+ if (!view_19) return;
4895
5226
  try {
4896
- const node_11 = view_18.state.doc.nodeAt(pmPos_17);
5227
+ const node_11 = view_19.state.doc.nodeAt(pmPos_17);
4897
5228
  if (!node_11 || node_11.type.name !== "image") return;
4898
5229
  const attrs = expectImageAttrs(node_11);
4899
5230
  if (attrs.displayMode === "float" || attrs.wrapType === "square" || attrs.wrapType === "tight" || attrs.wrapType === "through") {
@@ -4928,14 +5259,14 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4928
5259
  relativeTo: "margin"
4929
5260
  }
4930
5261
  };
4931
- const tr_4 = view_18.state.tr.setNodeMarkup(pmPos_17, void 0, mergeImageAttrs(node_11, { position: newPosition }));
4932
- view_18.dispatch(tr_4);
5262
+ const tr_4 = view_19.state.tr.setNodeMarkup(pmPos_17, void 0, mergeImageAttrs(node_11, { position: newPosition }));
5263
+ view_19.dispatch(tr_4);
4933
5264
  hiddenPMRef.current?.setNodeSelection(pmPos_17);
4934
5265
  } else {
4935
5266
  const dropPos = getPositionFromMouse(clientX_1, clientY_1);
4936
5267
  if (dropPos === null) return;
4937
5268
  if (dropPos === pmPos_17 || dropPos === pmPos_17 + 1) return;
4938
- let tr_5 = view_18.state.tr;
5269
+ let tr_5 = view_19.state.tr;
4939
5270
  tr_5 = tr_5.delete(pmPos_17, pmPos_17 + node_11.nodeSize);
4940
5271
  let selectionPos;
4941
5272
  if (dropPos <= pmPos_17) {
@@ -4947,7 +5278,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4947
5278
  selectionPos = Math.min(adjusted, tr_5.doc.content.size - 1);
4948
5279
  }
4949
5280
  hiddenPMRef.current?.setNodeSelection(selectionPos);
4950
- view_18.dispatch(tr_5);
5281
+ view_19.dispatch(tr_5);
4951
5282
  }
4952
5283
  } catch {}
4953
5284
  }, [getPositionFromMouse, zoom]);
@@ -4974,12 +5305,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4974
5305
  }
4975
5306
  return;
4976
5307
  }
4977
- if (e_7.target instanceof HTMLElement && e_7.target.closest("[data-hf-r-id]")) return;
4978
- let view_19 = hiddenPMRef.current?.getView();
4979
- if (!view_19) {
5308
+ if (e_7.target instanceof HTMLElement && e_7.target.closest("[data-hf-r-id], [data-note-kind][data-note-id]")) return;
5309
+ let view_20 = hiddenPMRef.current?.getView();
5310
+ if (!view_20) {
4980
5311
  ensureHiddenEditorView({ sync: true });
4981
- view_19 = hiddenPMRef.current?.getView();
4982
- if (view_19) {
5312
+ view_20 = hiddenPMRef.current?.getView();
5313
+ if (view_20) {
4983
5314
  if (isPlainTextInputEvent(e_7)) {
4984
5315
  e_7.preventDefault();
4985
5316
  queueHiddenEditorTextInput(e_7.key);
@@ -5002,11 +5333,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5002
5333
  }
5003
5334
  return;
5004
5335
  }
5005
- if (pendingHiddenEditorSelectionRef.current || queuedInputBeforeHiddenEditorRef.current.length > 0) applyPendingHiddenEditorInput(view_19);
5336
+ if (pendingHiddenEditorSelectionRef.current || queuedInputBeforeHiddenEditorRef.current.length > 0) applyPendingHiddenEditorInput(view_20);
5006
5337
  if (!hiddenPMRef.current?.isFocused()) focusHiddenEditor();
5007
5338
  if (e_7.key === " " && !e_7.ctrlKey && !e_7.metaKey && !e_7.nativeEvent.isComposing) {
5008
5339
  e_7.preventDefault();
5009
- dispatchEditorTextInput(view_19, " ");
5340
+ dispatchEditorTextInput(view_20, " ");
5010
5341
  return;
5011
5342
  }
5012
5343
  if (["PageUp", "PageDown"].includes(e_7.key) && !e_7.metaKey && !e_7.ctrlKey) {}
@@ -5034,7 +5365,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5034
5365
  */
5035
5366
  const handleContainerMouseDown = useCallback((e_8) => {
5036
5367
  if (e_8.target instanceof HTMLElement && e_8.target.closest(".docx-comments-sidebar")) return;
5037
- if (e_8.target instanceof HTMLElement && e_8.target.closest("[data-hf-r-id]")) return;
5368
+ if (e_8.target instanceof HTMLElement && e_8.target.closest("[data-hf-r-id], [data-note-kind][data-note-id]")) return;
5038
5369
  if (!hiddenPMRef.current?.isFocused()) focusHiddenEditor();
5039
5370
  }, [focusHiddenEditor]);
5040
5371
  useEffect(() => {
@@ -5100,19 +5431,19 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5100
5431
  /**
5101
5432
  * Run initial layout when document or view changes.
5102
5433
  */
5103
- const handleEditorViewReady = useCallback((view_20) => {
5104
- onEditorViewReadyRef.current?.(view_20);
5105
- anonymizationMatchesRef.current = anonymizationDecorationsKey.getState(view_20.state)?.matches ?? [];
5106
- const initialSuggestion = autocompleteSuggestionKey.getState(view_20.state)?.suggestion;
5434
+ const handleEditorViewReady = useCallback((view_21) => {
5435
+ onEditorViewReadyRef.current?.(view_21);
5436
+ anonymizationMatchesRef.current = anonymizationDecorationsKey.getState(view_21.state)?.matches ?? [];
5437
+ const initialSuggestion = autocompleteSuggestionKey.getState(view_21.state)?.suggestion;
5107
5438
  if (initialSuggestion !== void 0) autocompleteSuggestionRef.current = initialSuggestion;
5108
5439
  updateAutocompleteOverlay();
5109
- directivesRef.current = templateDirectivesKey.getState(view_20.state)?.ranges ?? [];
5110
- const previewState = templatePreviewValuesKey.getState(view_20.state);
5440
+ directivesRef.current = templateDirectivesKey.getState(view_21.state)?.ranges ?? [];
5441
+ const previewState = templatePreviewValuesKey.getState(view_21.state);
5111
5442
  templatePreviewRef.current = {
5112
5443
  entries: previewState?.entries ?? EMPTY_TEMPLATE_PREVIEW_ENTRIES,
5113
5444
  mode: previewState?.preview?.mode ?? "plain"
5114
5445
  };
5115
- const aiState = aiSuggestionDecorationsKey.getState(view_20.state);
5446
+ const aiState = aiSuggestionDecorationsKey.getState(view_21.state);
5116
5447
  aiSuggestionsRef.current = {
5117
5448
  suggestions: aiState?.suggestions ?? EMPTY_AI_SUGGESTIONS,
5118
5449
  focusedId: aiState?.focusedId ?? null
@@ -5120,16 +5451,16 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5120
5451
  const focusReadyView = () => {
5121
5452
  if (readOnly || !shouldFocusHiddenEditorOnReadyRef.current) return;
5122
5453
  requestAnimationFrame(() => {
5123
- if (hiddenPMRef.current?.getView() !== view_20) return;
5124
- applyPendingHiddenEditorInput(view_20);
5125
- view_20.focus();
5454
+ if (hiddenPMRef.current?.getView() !== view_21) return;
5455
+ applyPendingHiddenEditorInput(view_21);
5456
+ view_21.focus();
5126
5457
  setIsFocused(true);
5127
5458
  });
5128
5459
  };
5129
- if (layoutSessionRef.current.lastPmDoc?.eq(view_20.state.doc)) {
5460
+ if (layoutSessionRef.current.lastPmDoc?.eq(view_21.state.doc)) {
5130
5461
  const lastPreview = layoutSessionRef.current.lastTemplatePreview;
5131
- if (templatePreviewRef.current.mode !== lastPreview.mode || templatePreviewDirtyRange(lastPreview.entries, templatePreviewRef.current.entries) !== null) runLayoutPipeline$1(view_20.state, { reason: "manual" });
5132
- updateSelectionOverlay(view_20.state);
5462
+ if (templatePreviewRef.current.mode !== lastPreview.mode || templatePreviewDirtyRange(lastPreview.entries, templatePreviewRef.current.entries) !== null) runLayoutPipeline$1(view_21.state, { reason: "manual" });
5463
+ updateSelectionOverlay(view_21.state);
5133
5464
  updateAnonymizationOverlay();
5134
5465
  updateDirectivesOverlay();
5135
5466
  updateAISuggestionsOverlay();
@@ -5148,7 +5479,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5148
5479
  const runAfterFontWait_0 = (fontsLoaded_0) => {
5149
5480
  pendingInitialFontReadyLayoutRef.current = false;
5150
5481
  const currentView_0 = hiddenPMRef.current?.getView();
5151
- if (currentView_0 !== view_20) return;
5482
+ if (currentView_0 !== view_21) return;
5152
5483
  recordLayoutPhase("initial", "initial-fonts", performance.now() - fontWaitStartedAt_0);
5153
5484
  resetCanvasContext();
5154
5485
  clearAllCaches();
@@ -5158,7 +5489,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5158
5489
  suppressFontReadyUntilRef.current = performance.now() + INITIAL_FONT_READY_SUPPRESSION_MS;
5159
5490
  }
5160
5491
  };
5161
- waitForInitialLayoutFonts(document, view_20.state.doc).then(runAfterFontWait_0, () => runAfterFontWait_0(false));
5492
+ waitForInitialLayoutFonts(document, view_21.state.doc).then(runAfterFontWait_0, () => runAfterFontWait_0(false));
5162
5493
  focusReadyView();
5163
5494
  }, [
5164
5495
  applyPendingHiddenEditorInput,
@@ -5183,6 +5514,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5183
5514
  useEffect(() => {
5184
5515
  updateAISuggestionsOverlay();
5185
5516
  }, [updateAISuggestionsOverlay]);
5517
+ useEffect(() => {
5518
+ updatePassageHighlightOverlay();
5519
+ }, [updatePassageHighlightOverlay]);
5186
5520
  useEffect(() => {
5187
5521
  if (!onAnchorPositionsChange || !layout) return;
5188
5522
  let cancelled_0 = false;
@@ -5216,12 +5550,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5216
5550
  };
5217
5551
  const handleFontsLoaded = () => {
5218
5552
  if (pendingInitialFontReadyLayoutRef.current || performance.now() < suppressFontReadyUntilRef.current || layoutSessionRef.current.usedLoadedFonts) return;
5219
- const view_21 = hiddenPMRef.current?.getView();
5220
- if (view_21) {
5553
+ const view_22 = hiddenPMRef.current?.getView();
5554
+ if (view_22) {
5221
5555
  resetCanvasContext();
5222
5556
  clearAllCaches();
5223
- runLayoutPipelineRef.current(view_21.state, { reason: "font-ready" });
5224
- updateSelectionOverlayRef.current(view_21.state);
5557
+ runLayoutPipelineRef.current(view_22.state, { reason: "font-ready" });
5558
+ updateSelectionOverlayRef.current(view_22.state);
5225
5559
  }
5226
5560
  };
5227
5561
  fontSet.addEventListener("loading", handleFontsLoading);
@@ -5245,12 +5579,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5245
5579
  }
5246
5580
  registered = faces;
5247
5581
  if (faces.length === 0) return;
5248
- const view_22 = hiddenPMRef.current?.getView();
5249
- if (!view_22) return;
5582
+ const view_23 = hiddenPMRef.current?.getView();
5583
+ if (!view_23) return;
5250
5584
  resetCanvasContext();
5251
5585
  clearAllCaches();
5252
- runLayoutPipelineRef.current(view_22.state, { reason: "font-ready" });
5253
- updateSelectionOverlayRef.current(view_22.state);
5586
+ runLayoutPipelineRef.current(view_23.state, { reason: "font-ready" });
5587
+ updateSelectionOverlayRef.current(view_23.state);
5254
5588
  });
5255
5589
  return () => {
5256
5590
  cancelled_1 = true;
@@ -5262,12 +5596,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5262
5596
  let cancelled_2 = false;
5263
5597
  let registered_0 = [];
5264
5598
  const remeasureForFontChange = () => {
5265
- const view_23 = hiddenPMRef.current?.getView();
5266
- if (!view_23) return;
5599
+ const view_24 = hiddenPMRef.current?.getView();
5600
+ if (!view_24) return;
5267
5601
  resetCanvasContext();
5268
5602
  clearAllCaches();
5269
- runLayoutPipelineRef.current(view_23.state, { reason: "font-ready" });
5270
- updateSelectionOverlayRef.current(view_23.state);
5603
+ runLayoutPipelineRef.current(view_24.state, { reason: "font-ready" });
5604
+ updateSelectionOverlayRef.current(view_24.state);
5271
5605
  };
5272
5606
  loadHostFontFaces(hostFonts).then((faces_0) => {
5273
5607
  if (cancelled_2) {
@@ -5293,12 +5627,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5293
5627
  lastLayoutInputSignatureRef.current = layoutInputSignature;
5294
5628
  return;
5295
5629
  }
5296
- const view_24 = hiddenPMRef.current?.getView();
5297
- if (view_24) {
5630
+ const view_25 = hiddenPMRef.current?.getView();
5631
+ if (view_25) {
5298
5632
  const layoutInputsChanged = lastLayoutInputSignatureRef.current !== layoutInputSignature;
5299
5633
  lastLayoutInputSignatureRef.current = layoutInputSignature;
5300
- if (!layoutInputsChanged && view_24.state.doc === layoutSessionRef.current.lastPmDoc) return;
5301
- runLayoutPipelineRef.current(view_24.state, { reason: "layout-input" });
5634
+ if (!layoutInputsChanged && view_25.state.doc === layoutSessionRef.current.lastPmDoc) return;
5635
+ runLayoutPipelineRef.current(view_25.state, { reason: "layout-input" });
5302
5636
  }
5303
5637
  }, [document, layoutInputSignature]);
5304
5638
  useEffect(() => {
@@ -5316,7 +5650,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5316
5650
  return folioEditor;
5317
5651
  },
5318
5652
  getDocument() {
5319
- return folioEditor.getDocument();
5653
+ const current_0 = folioEditor.getDocument();
5654
+ return current_0 ? noteEditorRef.current?.snapshotDocument(current_0) ?? current_0 : null;
5320
5655
  },
5321
5656
  getState() {
5322
5657
  return folioEditor.getState();
@@ -5324,6 +5659,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5324
5659
  getView() {
5325
5660
  return folioEditor.getView();
5326
5661
  },
5662
+ getActiveView() {
5663
+ return getActiveEditorStory().view;
5664
+ },
5665
+ closeNoteStory() {
5666
+ noteEditorRef.current?.close();
5667
+ },
5327
5668
  getHfView(rId_0) {
5328
5669
  return hfPMsRef.current?.getView(rId_0) ?? null;
5329
5670
  },
@@ -5331,30 +5672,37 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5331
5672
  ensureHiddenEditorView(options_4);
5332
5673
  },
5333
5674
  focus() {
5334
- folioEditor.focus();
5675
+ getActiveEditorStory().view?.focus();
5335
5676
  setIsFocused(true);
5336
5677
  },
5337
5678
  blur() {
5338
- folioEditor.blur();
5679
+ const view_26 = getActiveEditorStory().view;
5680
+ if (view_26?.hasFocus() && view_26.dom instanceof HTMLElement) view_26.dom.blur();
5339
5681
  setIsFocused(false);
5340
5682
  },
5341
5683
  isFocused() {
5342
- return folioEditor.isFocused();
5684
+ return getActiveEditorStory().view?.hasFocus() ?? false;
5343
5685
  },
5344
5686
  dispatch(tr_6) {
5345
5687
  folioEditor.dispatch(tr_6);
5346
5688
  },
5347
5689
  undo() {
5348
- return folioEditor.undo();
5690
+ const target_4 = getActiveEditorStory();
5691
+ if (target_4.type === "none") return false;
5692
+ return undo(target_4.view.state, target_4.view.dispatch);
5349
5693
  },
5350
5694
  redo() {
5351
- return folioEditor.redo();
5695
+ const target_5 = getActiveEditorStory();
5696
+ if (target_5.type === "none") return false;
5697
+ return redo(target_5.view.state, target_5.view.dispatch);
5352
5698
  },
5353
5699
  canUndo() {
5354
- return folioEditor.canUndo();
5700
+ const target_6 = getActiveEditorStory();
5701
+ return target_6.type === "none" ? false : undo(target_6.view.state);
5355
5702
  },
5356
5703
  canRedo() {
5357
- return folioEditor.canRedo();
5704
+ const target_7 = getActiveEditorStory();
5705
+ return target_7.type === "none" ? false : redo(target_7.view.state);
5358
5706
  },
5359
5707
  setSelection(anchor_3, head_1) {
5360
5708
  folioEditor.setSelection(anchor_3, head_1);
@@ -5368,6 +5716,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5368
5716
  scrollToPosition: scrollToPositionImpl,
5369
5717
  scrollToPage: scrollToPageImpl,
5370
5718
  scrollToParaId: scrollToParaIdImpl,
5719
+ setPassageHighlight: setPassageHighlightImpl,
5371
5720
  getPageNumberForPmPos(pmPos_18) {
5372
5721
  const container_0 = pagesContainerRef.current;
5373
5722
  if (!container_0) return null;
@@ -5406,9 +5755,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5406
5755
  }), [
5407
5756
  ensureHiddenEditorView,
5408
5757
  folioEditor,
5758
+ getActiveEditorStory,
5409
5759
  scrollToPageImpl,
5410
5760
  scrollToParaIdImpl,
5411
- scrollToPositionImpl
5761
+ scrollToPositionImpl,
5762
+ setPassageHighlightImpl
5412
5763
  ]);
5413
5764
  useEffect(() => {
5414
5765
  if (!layout) return;
@@ -5475,6 +5826,18 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5475
5826
  ...styles !== void 0 ? { styles } : {},
5476
5827
  ..._theme !== void 0 ? { theme: _theme } : {}
5477
5828
  }),
5829
+ /* @__PURE__ */ jsx(NoteStoryEditor, {
5830
+ ref: noteEditorRef,
5831
+ document,
5832
+ onActiveChange: handleActiveNoteStoryChange,
5833
+ onDocumentChange: handleNoteDocumentChange,
5834
+ onStoryChange: handleNoteStoryTransaction,
5835
+ plugins: noteStoryPlugins,
5836
+ suggestionModeActive,
5837
+ ...suggestionAuthor !== void 0 ? { suggestionAuthor } : {},
5838
+ ...styles !== void 0 ? { styles } : {},
5839
+ ..._theme !== void 0 ? { theme: _theme } : {}
5840
+ }),
5478
5841
  /* @__PURE__ */ jsx(HiddenProseMirror, {
5479
5842
  ref: hiddenPMRef,
5480
5843
  document,
@@ -5488,6 +5851,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5488
5851
  onEditorViewReady: handleEditorViewReady,
5489
5852
  onEditorViewDestroy: handleEditorViewDestroy,
5490
5853
  onKeyDown: handleHiddenEditorKeyDown,
5854
+ ...onCopy !== void 0 ? { onCopy } : {},
5855
+ ...onCut !== void 0 ? { onCut } : {},
5856
+ ...onPaste !== void 0 ? { onPaste } : {},
5491
5857
  ...styles !== void 0 ? { styles } : {},
5492
5858
  externalPlugins,
5493
5859
  ...collaboration !== void 0 ? { collaboration } : {},
@@ -5517,6 +5883,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5517
5883
  selectedCanonical: selectedAnonymizationCanonical,
5518
5884
  selectionSeq: anonymizationSelectionSeq
5519
5885
  }),
5886
+ /* @__PURE__ */ jsx(PassageHighlightOverlay, { rects: passageHighlightRects }),
5520
5887
  /* @__PURE__ */ jsx(AutocompleteCaretOverlay, {
5521
5888
  caret: autocompleteCaret,
5522
5889
  text: autocompleteText,
@@ -5530,8 +5897,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5530
5897
  ranges: directivesRef.current
5531
5898
  }),
5532
5899
  /* @__PURE__ */ jsx(SelectionOverlay, {
5533
- selectionRects: hfEditMode ? EMPTY_SELECTION_RECTS : selectionRects,
5534
- caretPosition: hfEditMode ? null : caretPosition,
5900
+ selectionRects: hfEditMode || noteStoryActive ? EMPTY_SELECTION_RECTS : selectionRects,
5901
+ caretPosition: hfEditMode || noteStoryActive ? null : caretPosition,
5535
5902
  isFocused,
5536
5903
  pageGap,
5537
5904
  markCaretRect: true
@@ -6814,133 +7181,145 @@ function removePendingCommentMarkRange(view, range) {
6814
7181
  }
6815
7182
  //#endregion
6816
7183
  //#region src/components/ContentControlWidgetsOverlay.tsx
6817
- /**
6818
- * React shell for the content-control widgets plugin.
6819
- *
6820
- * The plugin (see `core/prosemirror/plugins/contentControlWidgets`) emits a
6821
- * `folio:content-control-widget` CustomEvent on the editor's view DOM
6822
- * whenever the user clicks a typed control. This component subscribes to
6823
- * those events and renders a small floating picker positioned at the
6824
- * anchor element — a list of menu items for dropdown / comboBox
6825
- * controls, a shared date picker for date controls — then dispatches back
6826
- * through `dispatchDropdownPick` / `dispatchDatePick` so the change rides
6827
- * the normal undo stack.
6828
- *
6829
- * The dropdown popover uses the injected `MenuItem` for visual + a11y
6830
- * consistency with the rest of the editor.
6831
- */
6832
- function parseListItems(raw) {
6833
- if (!raw) return [];
6834
- try {
6835
- const parsed = JSON.parse(raw);
6836
- if (!Array.isArray(parsed)) return [];
6837
- const out = [];
6838
- 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);
6839
- return out;
6840
- } catch {
6841
- return [];
6842
- }
6843
- }
6844
- function ContentControlWidgetsOverlay({ getEditorView }) {
7184
+ /** Thin React renderer for the shared content-control widget controller. */
7185
+ function ContentControlWidgetsOverlay(t0) {
7186
+ const $ = c(32);
7187
+ const { getEventRoot, getEditorView } = t0;
6845
7188
  const folioUI = useFolioUI();
6846
- const { Item: MenuItem } = folioUI.Menu;
7189
+ const { Root: Menu, Item: MenuItem } = folioUI.Menu;
6847
7190
  const DatePickerPopover = folioUI.DatePickerPopover;
6848
7191
  const t = useTranslations("folio");
6849
- const [open, setOpen] = useState(null);
6850
- const getEditorViewRef = useRef(getEditorView);
6851
- getEditorViewRef.current = getEditorView;
6852
- const close = useCallback(() => setOpen(null), []);
6853
- const viewDom = getEditorView()?.dom ?? null;
6854
- useEffect(() => {
6855
- if (!viewDom) return;
6856
- const onWidget = (event) => {
6857
- const detail = event.detail;
6858
- if (detail.kind === "dropdownOpen") {
6859
- const items = parseListItems(detail.listItemsJson);
6860
- setOpen({
6861
- kind: "dropdown",
6862
- pmPos: detail.pmPos,
6863
- items,
6864
- anchorRect: detail.anchor.getBoundingClientRect()
6865
- });
6866
- return;
6867
- }
6868
- if (detail.kind === "datePick") setOpen({
6869
- kind: "date",
6870
- pmPos: detail.pmPos,
6871
- anchorRect: detail.anchor.getBoundingClientRect()
6872
- });
6873
- };
6874
- viewDom.addEventListener(CONTENT_CONTROL_WIDGET_EVENT_NAME, onWidget);
6875
- return () => {
6876
- viewDom.removeEventListener(CONTENT_CONTROL_WIDGET_EVENT_NAME, onWidget);
6877
- };
6878
- }, [viewDom]);
6879
- useEffect(() => {
6880
- if (!open) return;
6881
- const onKey = (event_0) => {
6882
- if (event_0.key === "Escape") close();
6883
- };
6884
- const onScroll = () => close();
6885
- window.addEventListener("keydown", onKey);
6886
- window.addEventListener("scroll", onScroll, true);
6887
- return () => {
6888
- window.removeEventListener("keydown", onKey);
6889
- window.removeEventListener("scroll", onScroll, true);
7192
+ let t1;
7193
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
7194
+ t1 = new ContentControlWidgetController();
7195
+ $[0] = t1;
7196
+ } else t1 = $[0];
7197
+ const controller = t1;
7198
+ const snapshot = useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
7199
+ let t2;
7200
+ if ($[1] !== getEditorView) {
7201
+ t2 = getEditorView();
7202
+ $[1] = getEditorView;
7203
+ $[2] = t2;
7204
+ } else t2 = $[2];
7205
+ const view = t2;
7206
+ let t3;
7207
+ let t4;
7208
+ if ($[3] !== getEventRoot || $[4] !== view) {
7209
+ t3 = () => {
7210
+ controller.bind(view, getEventRoot());
7211
+ return () => controller.destroy();
6890
7212
  };
6891
- }, [open, close]);
6892
- const style = useMemo(() => {
6893
- if (!open) return;
6894
- return {
7213
+ t4 = [
7214
+ controller,
7215
+ getEventRoot,
7216
+ view
7217
+ ];
7218
+ $[3] = getEventRoot;
7219
+ $[4] = view;
7220
+ $[5] = t3;
7221
+ $[6] = t4;
7222
+ } else {
7223
+ t3 = $[5];
7224
+ t4 = $[6];
7225
+ }
7226
+ useEffect(t3, t4);
7227
+ let t5;
7228
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
7229
+ t5 = (value) => controller.pickDropdown(value);
7230
+ $[7] = t5;
7231
+ } else t5 = $[7];
7232
+ const onDropdownPick = t5;
7233
+ let t6;
7234
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
7235
+ t6 = (value_0) => value_0 ? controller.pickDate(value_0) : false;
7236
+ $[8] = t6;
7237
+ } else t6 = $[8];
7238
+ const onDateChange = t6;
7239
+ if (snapshot.status === "closed") return null;
7240
+ const t7 = `${snapshot.position.y}px`;
7241
+ const t8 = `${snapshot.position.x}px`;
7242
+ let t9;
7243
+ if ($[9] !== t7 || $[10] !== t8) {
7244
+ t9 = {
6895
7245
  position: "fixed",
6896
- top: `${open.anchorRect.bottom + 4}px`,
6897
- insetInlineStart: `${open.anchorRect.left}px`,
7246
+ top: t7,
7247
+ insetInlineStart: t8,
6898
7248
  zIndex: 9999
6899
7249
  };
6900
- }, [open]);
6901
- const openPmPos = open?.pmPos;
6902
- const onDropdownPick = useCallback((value) => {
6903
- const liveView = getEditorViewRef.current();
6904
- if (liveView && typeof openPmPos === "number") dispatchDropdownPick(liveView, openPmPos, value);
6905
- close();
6906
- }, [close, openPmPos]);
6907
- const onDatePick = useCallback((value_0) => {
6908
- const liveView_0 = getEditorViewRef.current();
6909
- if (liveView_0 && value_0.length > 0 && typeof openPmPos === "number") dispatchDatePick(liveView_0, openPmPos, value_0);
6910
- close();
6911
- }, [close, openPmPos]);
6912
- const handleDateChange = useCallback((value_1) => {
6913
- if (value_1) onDatePick(value_1);
6914
- }, [onDatePick]);
6915
- if (!open) return null;
6916
- return createPortal(/* @__PURE__ */ jsx("div", {
6917
- className: "folio-root",
6918
- style: { display: "contents" },
6919
- children: /* @__PURE__ */ jsxs("div", {
6920
- role: "dialog",
6921
- "aria-label": open.kind === "dropdown" ? t("contentControlDropdownAriaLabel") : t("contentControlDateAriaLabel"),
6922
- style,
6923
- className: "bg-popover text-popover-foreground min-w-[10rem] rounded-md border p-1 shadow-md",
6924
- children: [open.kind === "dropdown" && /* @__PURE__ */ jsx("div", {
6925
- role: "menu",
6926
- className: "flex flex-col",
6927
- children: open.items.length === 0 ? /* @__PURE__ */ jsx("div", {
6928
- className: "text-muted-foreground px-2 py-1 text-sm",
6929
- children: t("contentControlDropdownNoOptions")
6930
- }) : open.items.map((item) => /* @__PURE__ */ jsx(ContentControlDropdownItem, {
6931
- item,
6932
- MenuItem,
6933
- onPick: onDropdownPick
6934
- }, `${item.value}::${item.displayText}`))
6935
- }), open.kind === "date" && /* @__PURE__ */ jsx(DatePickerPopover, {
6936
- clearLabel: t("clearDate"),
6937
- defaultOpen: true,
6938
- onChange: handleDateChange,
6939
- showIcon: false,
6940
- value: null
6941
- })]
6942
- })
6943
- }), document.body);
7250
+ $[9] = t7;
7251
+ $[10] = t8;
7252
+ $[11] = t9;
7253
+ } else t9 = $[11];
7254
+ const style = t9;
7255
+ let t10;
7256
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
7257
+ t10 = { display: "contents" };
7258
+ $[12] = t10;
7259
+ } else t10 = $[12];
7260
+ let t11;
7261
+ if ($[13] !== snapshot.status || $[14] !== t) {
7262
+ t11 = snapshot.status === "dropdown" ? t("contentControlDropdownAriaLabel") : t("contentControlDateAriaLabel");
7263
+ $[13] = snapshot.status;
7264
+ $[14] = t;
7265
+ $[15] = t11;
7266
+ } else t11 = $[15];
7267
+ let t12;
7268
+ if ($[16] !== Menu || $[17] !== MenuItem || $[18] !== snapshot.items || $[19] !== snapshot.status || $[20] !== t) {
7269
+ t12 = snapshot.status === "dropdown" && /* @__PURE__ */ jsx(Menu, { children: /* @__PURE__ */ jsx("div", {
7270
+ role: "menu",
7271
+ className: "flex flex-col",
7272
+ children: snapshot.items.length === 0 ? /* @__PURE__ */ jsx("div", {
7273
+ className: "text-muted-foreground px-2 py-1 text-sm",
7274
+ children: t("contentControlDropdownNoOptions")
7275
+ }) : snapshot.items.map((item) => /* @__PURE__ */ jsx(ContentControlDropdownItem, {
7276
+ item,
7277
+ MenuItem,
7278
+ onPick: onDropdownPick
7279
+ }, `${item.value}::${item.displayText}`))
7280
+ }) });
7281
+ $[16] = Menu;
7282
+ $[17] = MenuItem;
7283
+ $[18] = snapshot.items;
7284
+ $[19] = snapshot.status;
7285
+ $[20] = t;
7286
+ $[21] = t12;
7287
+ } else t12 = $[21];
7288
+ let t13;
7289
+ if ($[22] !== DatePickerPopover || $[23] !== snapshot.currentValue || $[24] !== snapshot.status || $[25] !== t) {
7290
+ t13 = snapshot.status === "date" && /* @__PURE__ */ jsx(DatePickerPopover, {
7291
+ clearLabel: t("clearDate"),
7292
+ defaultOpen: true,
7293
+ onChange: onDateChange,
7294
+ showIcon: false,
7295
+ value: snapshot.currentValue
7296
+ });
7297
+ $[22] = DatePickerPopover;
7298
+ $[23] = snapshot.currentValue;
7299
+ $[24] = snapshot.status;
7300
+ $[25] = t;
7301
+ $[26] = t13;
7302
+ } else t13 = $[26];
7303
+ let t14;
7304
+ if ($[27] !== style || $[28] !== t11 || $[29] !== t12 || $[30] !== t13) {
7305
+ t14 = createPortal(/* @__PURE__ */ jsx("div", {
7306
+ className: "folio-root",
7307
+ style: t10,
7308
+ children: /* @__PURE__ */ jsxs("div", {
7309
+ role: "dialog",
7310
+ "aria-label": t11,
7311
+ style,
7312
+ className: "bg-popover text-popover-foreground min-w-[10rem] rounded-md border p-1 shadow-md",
7313
+ children: [t12, t13]
7314
+ })
7315
+ }), document.body);
7316
+ $[27] = style;
7317
+ $[28] = t11;
7318
+ $[29] = t12;
7319
+ $[30] = t13;
7320
+ $[31] = t14;
7321
+ } else t14 = $[31];
7322
+ return t14;
6944
7323
  }
6945
7324
  function ContentControlDropdownItem(t0) {
6946
7325
  const $ = c(7);
@@ -6968,209 +7347,13 @@ function ContentControlDropdownItem(t0) {
6968
7347
  }
6969
7348
  //#endregion
6970
7349
  //#region src/components/dialogs/findReplaceUtils.ts
6971
- /**
6972
- * Find & Replace Utility Functions
6973
- *
6974
- * Pure utility functions for text search, pattern matching, and document search.
6975
- * Extracted from FindReplaceDialog.tsx.
6976
- */
6977
- /**
6978
- * Create default find options
6979
- */
6980
- function createDefaultFindOptions() {
6981
- return {
6982
- matchCase: false,
6983
- matchWholeWord: false,
6984
- useRegex: false
6985
- };
6986
- }
6987
- /**
6988
- * Find all matches of search text in content
6989
- */
6990
- function findAllMatches(content, searchText, options) {
6991
- if (!content || !searchText) return [];
6992
- const matches = [];
6993
- let searchFor = searchText;
6994
- if (!options.matchCase) searchFor = searchText.toLowerCase();
6995
- const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
6996
- let pattern;
6997
- if (options.matchWholeWord) pattern = `\\b${escapeRegex(searchFor)}\\b`;
6998
- else pattern = escapeRegex(searchFor);
6999
- const flags = options.matchCase ? "g" : "gi";
7000
- const regex = new RegExp(pattern, flags);
7001
- let match;
7002
- while ((match = regex.exec(content)) !== null) {
7003
- matches.push({
7004
- start: match.index,
7005
- end: match.index + match[0].length
7006
- });
7007
- if (match[0].length === 0) regex.lastIndex++;
7008
- }
7009
- return matches;
7010
- }
7011
- /**
7012
- * Get plain text from a run
7013
- */
7014
- function getRunText(run) {
7015
- let text = "";
7016
- for (const item of run.content) if (item.type === "text") text += item.text;
7017
- else if (item.type === "tab") text += " ";
7018
- else if (item.type === "break" && item.breakType === "textWrapping") text += "\n";
7019
- return text;
7020
- }
7021
- function getHyperlinkText(hyperlink) {
7022
- let text = "";
7023
- for (const child of hyperlink.children) if (child.type === "run") text += getRunText(child);
7024
- return text;
7025
- }
7026
- function getParagraphContentText(content) {
7027
- if (content.type === "run") return getRunText(content);
7028
- if (content.type === "hyperlink") return getHyperlinkText(content);
7029
- if (content.type === "inlineSdt") {
7030
- let text = "";
7031
- for (const child of content.content) text += getParagraphContentText(child);
7032
- return text;
7033
- }
7034
- if (content.type === "simpleField") {
7035
- let text = "";
7036
- for (const child of content.content) {
7037
- if (child.type === "run") {
7038
- text += getRunText(child);
7039
- continue;
7040
- }
7041
- text += getHyperlinkText(child);
7042
- }
7043
- return text;
7044
- }
7045
- if (content.type === "complexField") {
7046
- let text = "";
7047
- for (const run of content.fieldResult) text += getRunText(run);
7048
- return text;
7049
- }
7050
- return "";
7051
- }
7052
- /**
7053
- * Get plain text from a paragraph
7054
- */
7055
- function getParagraphPlainText(paragraph) {
7056
- let text = "";
7057
- for (const item of paragraph.content) text += getParagraphContentText(item);
7058
- return text;
7059
- }
7060
- /**
7061
- * Find all matches in a document
7062
- */
7063
- function findInDocument(document, searchText, options) {
7064
- if (!document || !searchText) return [];
7065
- const matches = [];
7066
- const body = document.package.document;
7067
- if (!isDocumentBody(body)) return matches;
7068
- forEachParagraph(body.content, (block, paragraphIndex) => {
7069
- const paragraphMatches = findInParagraph(block, searchText, options, paragraphIndex);
7070
- matches.push(...paragraphMatches);
7071
- });
7072
- return matches;
7073
- }
7074
- function forEachParagraph(blocks, visit) {
7075
- let paragraphIndex = 0;
7076
- const walkBlocks = (items) => {
7077
- for (const block of items) {
7078
- if (isParagraph(block)) {
7079
- visit(block, paragraphIndex);
7080
- paragraphIndex++;
7081
- continue;
7082
- }
7083
- if (isTable(block)) {
7084
- walkTable(block);
7085
- continue;
7086
- }
7087
- if (isBlockSdt(block)) walkBlocks(block.content);
7088
- }
7089
- };
7090
- const walkTable = (table) => {
7091
- for (const row of table.rows) {
7092
- if (!isTableRow(row)) continue;
7093
- for (const cell of row.cells) {
7094
- if (!isTableCell(cell)) continue;
7095
- walkBlocks(cell.content);
7096
- }
7097
- }
7098
- };
7099
- walkBlocks(blocks);
7100
- }
7101
- function isRecord(value) {
7102
- return typeof value === "object" && value !== null;
7103
- }
7104
- function isDocumentBody(value) {
7105
- return isRecord(value) && Array.isArray(value["content"]);
7106
- }
7107
- function isParagraph(value) {
7108
- return isRecord(value) && value["type"] === "paragraph" && Array.isArray(value["content"]);
7109
- }
7110
- function isTable(value) {
7111
- return isRecord(value) && value["type"] === "table" && Array.isArray(value["rows"]);
7112
- }
7113
- function isTableRow(value) {
7114
- return isRecord(value) && Array.isArray(value["cells"]);
7115
- }
7116
- function isTableCell(value) {
7117
- return isRecord(value) && Array.isArray(value["content"]);
7118
- }
7119
- function isBlockSdt(value) {
7120
- return isRecord(value) && value["type"] === "blockSdt" && Array.isArray(value["content"]);
7121
- }
7122
- /**
7123
- * Find matches in a single paragraph
7124
- */
7125
- function findInParagraph(paragraph, searchText, options, paragraphIndex) {
7126
- const matches = [];
7127
- const paragraphText = getParagraphPlainText(paragraph);
7128
- if (!paragraphText) return matches;
7129
- const textMatches = findAllMatches(paragraphText, searchText, options);
7130
- for (const match of textMatches) {
7131
- const contentInfo = findContentAtOffset(paragraph, match.start);
7132
- matches.push({
7133
- paragraphIndex,
7134
- contentIndex: contentInfo.contentIndex,
7135
- startOffset: match.start,
7136
- endOffset: match.end,
7137
- text: paragraphText.slice(match.start, match.end)
7138
- });
7139
- }
7140
- return matches;
7141
- }
7142
- /**
7143
- * Find the content (run) at a specific character offset in a paragraph
7144
- */
7145
- function findContentAtOffset(paragraph, offset) {
7146
- let currentOffset = 0;
7147
- let contentIndex = 0;
7148
- for (const item of paragraph.content) {
7149
- const itemLength = getParagraphContentText(item).length;
7150
- if (currentOffset + itemLength > offset) return {
7151
- contentIndex,
7152
- runIndex: contentIndex,
7153
- offsetInContent: offset - currentOffset
7154
- };
7155
- currentOffset += itemLength;
7156
- contentIndex++;
7157
- }
7158
- return {
7159
- contentIndex: Math.max(0, paragraph.content.length - 1),
7160
- runIndex: Math.max(0, paragraph.content.length - 1),
7161
- offsetInContent: 0
7162
- };
7163
- }
7164
- /**
7165
- * Scroll to a match in the document
7166
- */
7167
- function scrollToMatch(containerElement, match) {
7350
+ const scrollToMatch = (containerElement, match) => {
7168
7351
  if (!containerElement) return;
7169
7352
  (containerElement.querySelector(`[data-paragraph-index="${match.paragraphIndex}"]`) ?? containerElement.querySelector(`.layout-paragraph[data-block-id="block-${match.paragraphIndex + 1}"]`) ?? containerElement.querySelectorAll(".layout-paragraph").item(match.paragraphIndex)).scrollIntoView({
7170
7353
  behavior: prefersReducedMotionBehavior(),
7171
7354
  block: "center"
7172
7355
  });
7173
- }
7356
+ };
7174
7357
  //#endregion
7175
7358
  //#region src/components/dialogs/useFindReplace.ts
7176
7359
  /**
@@ -12164,7 +12347,7 @@ function useFolioComments({ doc, autoOpenReviewSidebar, anchorPositions, editorC
12164
12347
  * - Error boundary
12165
12348
  * - Loading states
12166
12349
  */
12167
- const CommentsSidebar = lazy(() => import("./CommentsSidebar-Bopn32H9.js").then((m) => ({ default: m.CommentsSidebar })));
12350
+ const CommentsSidebar = lazy(() => import("./CommentsSidebar-ml91aGZ1.js").then((m) => ({ default: m.CommentsSidebar })));
12168
12351
  const TextContextMenu = lazy(() => import("./TextContextMenu-Ci7-M4oU.js").then((m) => ({ default: m.TextContextMenu })));
12169
12352
  const loadAttemptSelectiveSave = async () => {
12170
12353
  const { attemptSelectiveSave } = await import("@stll/folio-core/docx/selectiveSave");
@@ -12226,7 +12409,7 @@ function areActiveTrackedChangesEqual(a, b) {
12226
12409
  /**
12227
12410
  * DocxEditor - Complete DOCX editor component
12228
12411
  */
12229
- 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) {
12412
+ 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) {
12230
12413
  const t = useTranslations("folio");
12231
12414
  useEffect(() => {
12232
12415
  const onClipboardReadError = () => {
@@ -12474,6 +12657,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12474
12657
  canRedo: false,
12475
12658
  canUndo: false
12476
12659
  });
12660
+ const [activeNoteStory, setActiveNoteStory] = useState(null);
12477
12661
  const toolbarRefCallback = useCallback((el) => {
12478
12662
  toolbarWrapperRef.current = el;
12479
12663
  if (toolbarRoRef.current) {
@@ -12511,28 +12695,42 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12511
12695
  pushDocument,
12512
12696
  getHfView: (rId) => pagedEditorRef.current?.getHfView(rId) ?? null
12513
12697
  });
12514
- const getActiveEditorView = useCallback(() => {
12515
- if (hfEditPosition && hfEditorRef.current) return hfEditorRef.current.getView();
12516
- return pagedEditorRef.current?.getView();
12517
- }, [hfEditPosition]);
12698
+ let activeHfRId = hfEditIsFirstPage ? activeFirstFooterRId : activeFooterRId;
12699
+ if (hfEditPosition === "header") activeHfRId = hfEditIsFirstPage ? activeFirstHeaderRId : activeHeaderRId;
12700
+ const getActiveEditorStory = useCallback(() => {
12701
+ return resolveActiveEditorStory({
12702
+ bodyView: pagedEditorRef.current?.getView() ?? null,
12703
+ headerFooterView: hfEditPosition && hfEditorRef.current ? hfEditorRef.current.getView() : null,
12704
+ noteView: activeNoteStory ? pagedEditorRef.current?.getActiveView() ?? null : null
12705
+ });
12706
+ }, [activeNoteStory, hfEditPosition]);
12707
+ const getActiveEditorView = useCallback(() => getActiveEditorStory().view, [getActiveEditorStory]);
12518
12708
  const focusActiveEditor = useCallback(() => {
12519
- if (hfEditPosition && hfEditorRef.current) hfEditorRef.current.focus();
12709
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) hfEditorRef.current.focus();
12520
12710
  else pagedEditorRef.current?.focus();
12521
- }, [hfEditPosition]);
12711
+ }, [getActiveEditorStory]);
12522
12712
  const undoActiveEditor = useCallback(() => {
12523
- if (hfEditPosition && hfEditorRef.current) hfEditorRef.current.undo();
12713
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) hfEditorRef.current.undo();
12524
12714
  else {
12525
12715
  pagedEditorRef.current?.undo();
12526
12716
  requestAnimationFrame(refreshBodyHistoryAvailability);
12527
12717
  }
12528
- }, [hfEditPosition, refreshBodyHistoryAvailability]);
12718
+ }, [getActiveEditorStory, refreshBodyHistoryAvailability]);
12529
12719
  const redoActiveEditor = useCallback(() => {
12530
- if (hfEditPosition && hfEditorRef.current) hfEditorRef.current.redo();
12720
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) hfEditorRef.current.redo();
12531
12721
  else {
12532
12722
  pagedEditorRef.current?.redo();
12533
12723
  requestAnimationFrame(refreshBodyHistoryAvailability);
12534
12724
  }
12535
- }, [hfEditPosition, refreshBodyHistoryAvailability]);
12725
+ }, [getActiveEditorStory, refreshBodyHistoryAvailability]);
12726
+ const handleActiveNoteStoryChange = useCallback((story) => {
12727
+ setActiveNoteStory(story);
12728
+ if (story && hfEditPosition) handleBodyClick();
12729
+ }, [handleBodyClick, hfEditPosition]);
12730
+ const handleHeaderFooterStoryOpen = useCallback((position, pageNumber) => {
12731
+ pagedEditorRef.current?.closeNoteStory();
12732
+ handleHeaderFooterDoubleClick(position, pageNumber);
12733
+ }, [handleHeaderFooterDoubleClick]);
12536
12734
  const findReplace = useFindReplace$1();
12537
12735
  const [showPageSetup, setShowPageSetup] = useState(false);
12538
12736
  const { hyperlinkPopupData, handleHyperlinkClick, handleHyperlinkPopupNavigate, handleHyperlinkPopupCopy, handleHyperlinkPopupEdit, handleHyperlinkPopupRemove, handleHyperlinkPopupClose } = useHyperlinkHandlers({
@@ -12679,8 +12877,11 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12679
12877
  if (!history.state) return null;
12680
12878
  let doc_0 = structuredClone(history.state);
12681
12879
  const pmDoc = pagedEditorRef.current?.getDocument();
12682
- if (pmDoc) doc_0.package.document.content = pmDoc.package.document.content;
12683
- else doc_0 = normalizeBaseDirection(doc_0);
12880
+ if (pmDoc) {
12881
+ doc_0.package.document.content = pmDoc.package.document.content;
12882
+ if (pmDoc.package.footnotes !== void 0) doc_0.package.footnotes = pmDoc.package.footnotes;
12883
+ if (pmDoc.package.endnotes !== void 0) doc_0.package.endnotes = pmDoc.package.endnotes;
12884
+ } else doc_0 = normalizeBaseDirection(doc_0);
12684
12885
  const editor = pagedEditorRef.current;
12685
12886
  if (editor) {
12686
12887
  const flushBag = (bag) => {
@@ -13455,14 +13656,16 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13455
13656
  if (readOnly) return;
13456
13657
  const { from: from_7, to: to_7 } = view_12.state.selection;
13457
13658
  const text_2 = view_12.state.doc.textBetween(from_7, to_7, "\n");
13458
- navigator.clipboard.writeText(text_2);
13659
+ navigator.clipboard.writeText(text_2).catch(() => void 0);
13459
13660
  view_12.dispatch(view_12.state.tr.deleteSelection());
13661
+ onCut?.();
13460
13662
  break;
13461
13663
  }
13462
13664
  case "copy": {
13463
13665
  const { from: cf, to: ct } = view_12.state.selection;
13464
13666
  const copied = view_12.state.doc.textBetween(cf, ct, "\n");
13465
- navigator.clipboard.writeText(copied);
13667
+ navigator.clipboard.writeText(copied).catch(() => void 0);
13668
+ onCopy?.();
13466
13669
  break;
13467
13670
  }
13468
13671
  case "paste":
@@ -13487,7 +13690,10 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13487
13690
  } catch {
13488
13691
  try {
13489
13692
  const text_0 = await navigator.clipboard.readText();
13490
- if (text_0) view_12.dispatch(view_12.state.tr.insertText(text_0));
13693
+ if (text_0) {
13694
+ view_12.dispatch(view_12.state.tr.insertText(text_0));
13695
+ onPaste?.();
13696
+ }
13491
13697
  } catch {}
13492
13698
  }
13493
13699
  break;
@@ -13497,6 +13703,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13497
13703
  if (text && !view_12.isDestroyed) {
13498
13704
  const slice = buildPlainTextSlice(text, view_12.state.schema);
13499
13705
  view_12.dispatch(view_12.state.tr.replaceSelection(slice).scrollIntoView());
13706
+ onPaste?.();
13500
13707
  }
13501
13708
  } catch {
13502
13709
  toast(t("clipboardReadFailed"));
@@ -13570,6 +13777,9 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13570
13777
  getActiveEditorView,
13571
13778
  focusActiveEditor,
13572
13779
  onCustomContextAction,
13780
+ onCopy,
13781
+ onCut,
13782
+ onPaste,
13573
13783
  readOnly,
13574
13784
  contextMenu.selectionRange.from,
13575
13785
  contextMenu.selectionRange.to,
@@ -13706,8 +13916,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13706
13916
  },
13707
13917
  getCurrentPage: () => scrollPageInfo.currentPage,
13708
13918
  getTotalPages: () => scrollPageInfo.totalPages,
13709
- scrollToPage: (pageNumber) => {
13710
- pagedEditorRef.current?.scrollToPage(pageNumber);
13919
+ scrollToPage: (pageNumber_0) => {
13920
+ pagedEditorRef.current?.scrollToPage(pageNumber_0);
13711
13921
  },
13712
13922
  scrollToParaId: (paraId, options_0) => pagedEditorRef.current?.scrollToParaId(paraId, options_0) ?? false,
13713
13923
  openPrintPreview: handleDirectPrint,
@@ -13857,13 +14067,13 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13857
14067
  return rejectAIEditRevision(revisionId_0)(view_24.state, view_24.dispatch);
13858
14068
  },
13859
14069
  undo: () => {
13860
- if (hfEditPosition && hfEditorRef.current) return hfEditorRef.current.undo();
14070
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) return hfEditorRef.current.undo();
13861
14071
  const undone = pagedEditorRef.current?.undo() ?? false;
13862
14072
  requestAnimationFrame(refreshBodyHistoryAvailability);
13863
14073
  return undone;
13864
14074
  },
13865
14075
  redo: () => {
13866
- if (hfEditPosition && hfEditorRef.current) return hfEditorRef.current.redo();
14076
+ if (getActiveEditorStory().type === "headerFooter" && hfEditorRef.current) return hfEditorRef.current.redo();
13867
14077
  const redone = pagedEditorRef.current?.redo() ?? false;
13868
14078
  requestAnimationFrame(refreshBodyHistoryAvailability);
13869
14079
  return redone;
@@ -13900,104 +14110,141 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
13900
14110
  });
13901
14111
  return true;
13902
14112
  },
13903
- showInDocument: (target_1, snapshot_2) => {
14113
+ highlightPassage: ({ blockId: blockId_0, text: text_5, snapshot: snapshot_2 }) => {
13904
14114
  const view_27 = pagedEditorRef.current?.getView();
13905
- if (!view_27) return false;
13906
- const range_4 = target_1.type === "textRange" ? resolveFolioAITextRange({
13907
- range: target_1,
14115
+ if (!view_27) return "none";
14116
+ const passageRange = resolvePassageRange({
14117
+ blockId: blockId_0,
14118
+ text: text_5,
13908
14119
  doc: view_27.state.doc,
13909
14120
  snapshot: snapshot_2
13910
- }) : resolveFolioAIBlockRange({
13911
- blockId: target_1.blockId,
14121
+ });
14122
+ if (passageRange !== null) {
14123
+ pagedEditorRef.current?.setPassageHighlight(passageRange);
14124
+ requestAnimationFrame(() => {
14125
+ pagedEditorRef.current?.scrollToPosition(passageRange.from);
14126
+ });
14127
+ return "passage";
14128
+ }
14129
+ pagedEditorRef.current?.setPassageHighlight(null);
14130
+ const blockRange = resolveFolioAIBlockRange({
14131
+ blockId: blockId_0,
13912
14132
  doc: view_27.state.doc,
13913
14133
  snapshot: snapshot_2
13914
14134
  });
13915
- if (range_4 === null) return false;
13916
- const { from: from_10, to: to_10 } = range_4;
14135
+ if (blockRange === null) return "none";
14136
+ const paraId_0 = getFolioParaIdFromBlockId(blockId_0);
14137
+ if (paraId_0 !== null && pagedEditorRef.current?.scrollToParaId(paraId_0, { highlight: {} })) return "block";
14138
+ const { from: from_10, to: to_10 } = blockRange;
13917
14139
  const $from_1 = view_27.state.doc.resolve(from_10);
13918
14140
  const $to_1 = view_27.state.doc.resolve(to_10);
13919
14141
  view_27.dispatch(view_27.state.tr.setSelection(TextSelection.between($from_1, $to_1)));
13920
14142
  requestAnimationFrame(() => {
13921
14143
  pagedEditorRef.current?.scrollToPosition(from_10);
13922
14144
  });
13923
- return true;
14145
+ return "block";
13924
14146
  },
13925
- getTrackedChanges: () => {
14147
+ clearPassageHighlight: () => {
14148
+ pagedEditorRef.current?.setPassageHighlight(null);
14149
+ },
14150
+ showInDocument: (target_1, snapshot_3) => {
13926
14151
  const view_28 = pagedEditorRef.current?.getView();
13927
- return view_28 ? getTrackedChangesFromDoc(view_28.state.doc) : [];
14152
+ if (!view_28) return false;
14153
+ const range_4 = target_1.type === "textRange" ? resolveFolioAITextRange({
14154
+ range: target_1,
14155
+ doc: view_28.state.doc,
14156
+ snapshot: snapshot_3
14157
+ }) : resolveFolioAIBlockRange({
14158
+ blockId: target_1.blockId,
14159
+ doc: view_28.state.doc,
14160
+ snapshot: snapshot_3
14161
+ });
14162
+ if (range_4 === null) return false;
14163
+ const { from: from_11, to: to_11 } = range_4;
14164
+ const $from_2 = view_28.state.doc.resolve(from_11);
14165
+ const $to_2 = view_28.state.doc.resolve(to_11);
14166
+ view_28.dispatch(view_28.state.tr.setSelection(TextSelection.between($from_2, $to_2)));
14167
+ requestAnimationFrame(() => {
14168
+ pagedEditorRef.current?.scrollToPosition(from_11);
14169
+ });
14170
+ return true;
13928
14171
  },
13929
- getCommentAnchors: () => {
14172
+ getTrackedChanges: () => {
13930
14173
  const view_29 = pagedEditorRef.current?.getView();
13931
- return view_29 ? getCommentAnchorsFromDoc(view_29.state.doc) : [];
14174
+ return view_29 ? getTrackedChangesFromDoc(view_29.state.doc) : [];
13932
14175
  },
13933
- getSelectionText: () => {
14176
+ getCommentAnchors: () => {
13934
14177
  const view_30 = pagedEditorRef.current?.getView();
13935
- return view_30 ? getSelectedText(view_30.state) : "";
14178
+ return view_30 ? getCommentAnchorsFromDoc(view_30.state.doc) : [];
13936
14179
  },
13937
- getPageText: (page_0) => {
14180
+ getSelectionText: () => {
13938
14181
  const view_31 = pagedEditorRef.current?.getView();
13939
- if (!view_31) return null;
13940
- return getPageTextFromLayout(pagedEditorRef.current?.getEditor()?.getLayout() ?? null, view_31.state.doc, page_0);
14182
+ return view_31 ? getSelectedText(view_31.state) : "";
13941
14183
  },
13942
- getTargetPage: (target_2, snapshot_3) => {
14184
+ getPageText: (page_0) => {
13943
14185
  const view_32 = pagedEditorRef.current?.getView();
13944
14186
  if (!view_32) return null;
14187
+ return getPageTextFromLayout(pagedEditorRef.current?.getEditor()?.getLayout() ?? null, view_32.state.doc, page_0);
14188
+ },
14189
+ getTargetPage: (target_2, snapshot_4) => {
14190
+ const view_33 = pagedEditorRef.current?.getView();
14191
+ if (!view_33) return null;
13945
14192
  const range_5 = target_2.type === "textRange" ? resolveFolioAITextRange({
13946
14193
  range: target_2,
13947
- doc: view_32.state.doc,
13948
- snapshot: snapshot_3
14194
+ doc: view_33.state.doc,
14195
+ snapshot: snapshot_4
13949
14196
  }) : resolveFolioAIBlockRange({
13950
14197
  blockId: target_2.blockId,
13951
- doc: view_32.state.doc,
13952
- snapshot: snapshot_3
14198
+ doc: view_33.state.doc,
14199
+ snapshot: snapshot_4
13953
14200
  });
13954
14201
  if (range_5 === null) return null;
13955
14202
  return pagedEditorRef.current?.getPageNumberForPmPos(range_5.from) ?? null;
13956
14203
  },
13957
14204
  getContentControls: (filter = {}) => {
13958
- const view_33 = pagedEditorRef.current?.getView();
13959
- if (!view_33) return [];
13960
- return findBlockSdtMatches(view_33.state.doc, filter).map((match_0) => ({
14205
+ const view_34 = pagedEditorRef.current?.getView();
14206
+ if (!view_34) return [];
14207
+ return findBlockSdtMatches(view_34.state.doc, filter).map((match_0) => ({
13961
14208
  properties: blockSdtAttrsToSdtProperties(match_0.node),
13962
14209
  path: match_0.path,
13963
14210
  pmPos: match_0.pos
13964
14211
  }));
13965
14212
  },
13966
14213
  scrollToContentControl: (filter_0) => {
13967
- const view_34 = pagedEditorRef.current?.getView();
13968
- if (!view_34) return false;
13969
- const match_1 = findBlockSdtMatch(view_34.state.doc, filter_0);
14214
+ const view_35 = pagedEditorRef.current?.getView();
14215
+ if (!view_35) return false;
14216
+ const match_1 = findBlockSdtMatch(view_35.state.doc, filter_0);
13970
14217
  if (!match_1) return false;
13971
14218
  const inside = match_1.pos + 1;
13972
- const $pos = view_34.state.doc.resolve(inside);
13973
- view_34.dispatch(view_34.state.tr.setSelection(TextSelection.near($pos)));
14219
+ const $pos = view_35.state.doc.resolve(inside);
14220
+ view_35.dispatch(view_35.state.tr.setSelection(TextSelection.near($pos)));
13974
14221
  requestAnimationFrame(() => {
13975
14222
  pagedEditorRef.current?.scrollToPosition(inside);
13976
14223
  });
13977
14224
  return true;
13978
14225
  },
13979
14226
  setContentControlContent: (filter_1, input, options_2 = {}) => {
13980
- const view_35 = pagedEditorRef.current?.getView();
13981
- if (!view_35) return false;
13982
- const tr_0 = typeof input === "string" ? setContentControlContentTr(view_35.state, filter_1, input, options_2) : setContentControlContentBlocksTr(view_35.state, filter_1, input, options_2);
14227
+ const view_36 = pagedEditorRef.current?.getView();
14228
+ if (!view_36) return false;
14229
+ const tr_0 = typeof input === "string" ? setContentControlContentTr(view_36.state, filter_1, input, options_2) : setContentControlContentBlocksTr(view_36.state, filter_1, input, options_2);
13983
14230
  if (!tr_0) return false;
13984
- view_35.dispatch(tr_0);
14231
+ view_36.dispatch(tr_0);
13985
14232
  return true;
13986
14233
  },
13987
14234
  setContentControlValue: (filter_2, input_0, options_3 = {}) => {
13988
- const view_36 = pagedEditorRef.current?.getView();
13989
- if (!view_36) return false;
13990
- const tr_1 = setContentControlValueTr(view_36.state, filter_2, input_0, options_3);
14235
+ const view_37 = pagedEditorRef.current?.getView();
14236
+ if (!view_37) return false;
14237
+ const tr_1 = setContentControlValueTr(view_37.state, filter_2, input_0, options_3);
13991
14238
  if (!tr_1) return false;
13992
- view_36.dispatch(tr_1);
14239
+ view_37.dispatch(tr_1);
13993
14240
  return true;
13994
14241
  },
13995
14242
  removeContentControl: (filter_3, options_4 = {}) => {
13996
- const view_37 = pagedEditorRef.current?.getView();
13997
- if (!view_37) return false;
13998
- const tr_2 = removeContentControlTr(view_37.state, filter_3, options_4);
14243
+ const view_38 = pagedEditorRef.current?.getView();
14244
+ if (!view_38) return false;
14245
+ const tr_2 = removeContentControlTr(view_38.state, filter_3, options_4);
13999
14246
  if (!tr_2) return false;
14000
- view_37.dispatch(tr_2);
14247
+ view_38.dispatch(tr_2);
14001
14248
  return true;
14002
14249
  }
14003
14250
  }), [
@@ -14014,7 +14261,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14014
14261
  replaceComments,
14015
14262
  commentsRef,
14016
14263
  commentsDirtyRef,
14017
- hfEditPosition,
14264
+ getActiveEditorStory,
14018
14265
  refreshBodyHistoryAvailability
14019
14266
  ]);
14020
14267
  const getHfTargetElement = useCallback((pos_0) => {
@@ -14027,6 +14274,17 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14027
14274
  value: mode_0,
14028
14275
  label: t(DISPLAY_MODE_LABEL_KEYS[mode_0])
14029
14276
  })), [t]);
14277
+ const activeHistoryAvailability = (() => {
14278
+ if (activeNoteStory) return {
14279
+ canRedo: pagedEditorRef.current?.canRedo() ?? false,
14280
+ canUndo: pagedEditorRef.current?.canUndo() ?? false
14281
+ };
14282
+ if (hfEditPosition) return {
14283
+ canRedo: history.canRedo,
14284
+ canUndo: history.canUndo
14285
+ };
14286
+ return bodyHistoryAvailability;
14287
+ })();
14030
14288
  const toolbarChildren = toolbarExtra ?? null;
14031
14289
  const visibleCommentAuthorCount = commentAuthors.filter((commentAuthor) => visibleCommentAuthorSet.has(commentAuthor)).length;
14032
14290
  const allCommentAuthorsVisible = commentAuthors.length > 0 && showCommentsSidebar && visibleCommentAuthorCount === commentAuthors.length;
@@ -14068,39 +14326,39 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14068
14326
  if (isDisplayMode(value)) setDisplayMode(value);
14069
14327
  }, [setDisplayMode]);
14070
14328
  const handleAcceptActiveChange = useCallback(() => {
14071
- const view_38 = pagedEditorRef.current?.getView();
14072
- if (!view_38) return;
14073
- const { from: from_11, to: to_11 } = view_38.state.selection;
14074
- const range_6 = findChangeAtPosition(view_38.state, from_11, to_11);
14075
- acceptChange(range_6.from, range_6.to)(view_38.state, view_38.dispatch);
14076
- }, []);
14077
- const handleRejectActiveChange = useCallback(() => {
14078
14329
  const view_39 = pagedEditorRef.current?.getView();
14079
14330
  if (!view_39) return;
14080
14331
  const { from: from_12, to: to_12 } = view_39.state.selection;
14081
- const range_7 = findChangeAtPosition(view_39.state, from_12, to_12);
14082
- rejectChange(range_7.from, range_7.to)(view_39.state, view_39.dispatch);
14332
+ const range_6 = findChangeAtPosition(view_39.state, from_12, to_12);
14333
+ acceptChange(range_6.from, range_6.to)(view_39.state, view_39.dispatch);
14083
14334
  }, []);
14084
- const handlePreviousChange = useCallback(() => {
14335
+ const handleRejectActiveChange = useCallback(() => {
14085
14336
  const view_40 = pagedEditorRef.current?.getView();
14086
14337
  if (!view_40) return;
14087
- const { from: from_13 } = view_40.state.selection;
14088
- const change = findPreviousChange(view_40.state, from_13);
14338
+ const { from: from_13, to: to_13 } = view_40.state.selection;
14339
+ const range_7 = findChangeAtPosition(view_40.state, from_13, to_13);
14340
+ rejectChange(range_7.from, range_7.to)(view_40.state, view_40.dispatch);
14341
+ }, []);
14342
+ const handlePreviousChange = useCallback(() => {
14343
+ const view_41 = pagedEditorRef.current?.getView();
14344
+ if (!view_41) return;
14345
+ const { from: from_14 } = view_41.state.selection;
14346
+ const change = findPreviousChange(view_41.state, from_14);
14089
14347
  if (!change) return;
14090
- view_40.dispatch(view_40.state.tr.setSelection(TextSelection.create(view_40.state.doc, change.from, change.to)));
14091
- view_40.focus();
14348
+ view_41.dispatch(view_41.state.tr.setSelection(TextSelection.create(view_41.state.doc, change.from, change.to)));
14349
+ view_41.focus();
14092
14350
  requestAnimationFrame(() => {
14093
14351
  pagedEditorRef.current?.scrollToPosition(change.from);
14094
14352
  });
14095
14353
  }, []);
14096
14354
  const handleNextChange = useCallback(() => {
14097
- const view_41 = pagedEditorRef.current?.getView();
14098
- if (!view_41) return;
14099
- const { to: to_13 } = view_41.state.selection;
14100
- const change_0 = findNextChange(view_41.state, to_13);
14355
+ const view_42 = pagedEditorRef.current?.getView();
14356
+ if (!view_42) return;
14357
+ const { to: to_14 } = view_42.state.selection;
14358
+ const change_0 = findNextChange(view_42.state, to_14);
14101
14359
  if (!change_0) return;
14102
- view_41.dispatch(view_41.state.tr.setSelection(TextSelection.create(view_41.state.doc, change_0.from, change_0.to)));
14103
- view_41.focus();
14360
+ view_42.dispatch(view_42.state.tr.setSelection(TextSelection.create(view_42.state.doc, change_0.from, change_0.to)));
14361
+ view_42.focus();
14104
14362
  requestAnimationFrame(() => {
14105
14363
  pagedEditorRef.current?.scrollToPosition(change_0.from);
14106
14364
  });
@@ -14270,8 +14528,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14270
14528
  requestAnimationFrame(syncCommentHighlightStyles);
14271
14529
  }, [onScrollTopChange, syncCommentHighlightStyles]);
14272
14530
  const handlePagedSelectionChange = useCallback((_from, _to) => {
14273
- const view_42 = getActiveEditorView() ?? pagedEditorRef.current?.getView() ?? null;
14274
- handleSelectionChange(view_42 ? extractSelectionState(view_42.state) : null);
14531
+ const view_43 = getActiveEditorView() ?? pagedEditorRef.current?.getView() ?? null;
14532
+ handleSelectionChange(view_43 ? extractSelectionState(view_43.state) : null);
14275
14533
  }, [getActiveEditorView, handleSelectionChange]);
14276
14534
  const handleTotalPagesChange = useCallback((totalPages) => {
14277
14535
  setScrollPageInfo((previous) => updateScrollPageTotal(previous, totalPages));
@@ -14291,14 +14549,14 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14291
14549
  setActiveCommentId,
14292
14550
  updateComments
14293
14551
  ]);
14294
- const handleCommentReply = useCallback((id_2, text_5) => {
14295
- updateComments((previous_2) => [...previous_2, createComment(text_5, author, id_2)]);
14552
+ const handleCommentReply = useCallback((id_2, text_6) => {
14553
+ updateComments((previous_2) => [...previous_2, createComment(text_6, author, id_2)]);
14296
14554
  }, [author, updateComments]);
14297
14555
  const handleAddComment = useCallback((addText) => {
14298
14556
  const comment_3 = createComment(addText, author);
14299
- const view_43 = pagedEditorRef.current?.getView();
14300
- if (!view_43 || !commentSelectionRange) return false;
14301
- if (!applyCommentMarkRange(view_43, commentSelectionRange, comment_3.id, { replacePending: true })) return false;
14557
+ const view_44 = pagedEditorRef.current?.getView();
14558
+ if (!view_44 || !commentSelectionRange) return false;
14559
+ if (!applyCommentMarkRange(view_44, commentSelectionRange, comment_3.id, { replacePending: true })) return false;
14302
14560
  const commentAuthor_2 = getCommentAuthorKey(comment_3.author);
14303
14561
  setVisibleCommentAuthors((current) => {
14304
14562
  if (current === null) return null;
@@ -14328,12 +14586,12 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14328
14586
  syncCommentHighlightStyles,
14329
14587
  updateComments
14330
14588
  ]);
14331
- const handleTrackedChangeReply = useCallback((revisionId_2, text_6) => {
14332
- updateComments((previous_4) => [...previous_4, createComment(text_6, author, revisionId_2)]);
14589
+ const handleTrackedChangeReply = useCallback((revisionId_2, text_7) => {
14590
+ updateComments((previous_4) => [...previous_4, createComment(text_7, author, revisionId_2)]);
14333
14591
  }, [author, updateComments]);
14334
14592
  const handleCancelAddComment = useCallback(() => {
14335
- const view_44 = pagedEditorRef.current?.getView();
14336
- if (view_44 && commentSelectionRange) removePendingCommentMarkRange(view_44, commentSelectionRange);
14593
+ const view_45 = pagedEditorRef.current?.getView();
14594
+ if (view_45 && commentSelectionRange) removePendingCommentMarkRange(view_45, commentSelectionRange);
14337
14595
  setIsAddingComment(false);
14338
14596
  setCommentSelectionRange(null);
14339
14597
  setAddCommentYPosition(null);
@@ -14343,16 +14601,16 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14343
14601
  setCommentSelectionRange,
14344
14602
  setIsAddingComment
14345
14603
  ]);
14346
- const handleSidebarAcceptChange = useCallback((from_14, to_14) => {
14347
- const view_45 = pagedEditorRef.current?.getView();
14348
- if (!view_45) return;
14349
- acceptChange(from_14, to_14)(view_45.state, view_45.dispatch);
14350
- extractTrackedChanges();
14351
- }, [extractTrackedChanges]);
14352
- const handleSidebarRejectChange = useCallback((from_15, to_15) => {
14604
+ const handleSidebarAcceptChange = useCallback((from_15, to_15) => {
14353
14605
  const view_46 = pagedEditorRef.current?.getView();
14354
14606
  if (!view_46) return;
14355
- rejectChange(from_15, to_15)(view_46.state, view_46.dispatch);
14607
+ acceptChange(from_15, to_15)(view_46.state, view_46.dispatch);
14608
+ extractTrackedChanges();
14609
+ }, [extractTrackedChanges]);
14610
+ const handleSidebarRejectChange = useCallback((from_16, to_16) => {
14611
+ const view_47 = pagedEditorRef.current?.getView();
14612
+ if (!view_47) return;
14613
+ rejectChange(from_16, to_16)(view_47.state, view_47.dispatch);
14356
14614
  extractTrackedChanges();
14357
14615
  }, [extractTrackedChanges]);
14358
14616
  const commentsPageWidth = history.state?.package.document.finalSectionProperties?.pageWidth;
@@ -14398,8 +14656,6 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14398
14656
  showCommentsSidebar,
14399
14657
  visibleComments
14400
14658
  ]);
14401
- let activeHfRId = hfEditIsFirstPage ? activeFirstFooterRId : activeFooterRId;
14402
- if (hfEditPosition === "header") activeHfRId = hfEditIsFirstPage ? activeFirstHeaderRId : activeHeaderRId;
14403
14659
  const getActiveHfView = useCallback(() => activeHfRId ? pagedEditorRef.current?.getHfView(activeHfRId) ?? null : null, [activeHfRId]);
14404
14660
  const handleOutlineHeadingClick = useCallback((pmPos) => {
14405
14661
  pagedEditorRef.current?.scrollToPosition(pmPos);
@@ -14423,10 +14679,15 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14423
14679
  handleContextMenuAction(action_3);
14424
14680
  }, [handleContextMenuAction]);
14425
14681
  const getBodyEditorView = useCallback(() => pagedEditorRef.current?.getView() ?? null, []);
14682
+ const getContentControlEventRoot = useCallback(() => {
14683
+ if (readOnly) return null;
14684
+ const root = containerRef.current?.querySelector(".paged-editor__pages");
14685
+ return root instanceof HTMLElement ? root : null;
14686
+ }, [readOnly]);
14426
14687
  const closeTableProperties = useCallback(() => setTablePropsOpen(false), []);
14427
14688
  const applyTableProperties = useCallback((props_0) => {
14428
- const view_47 = getActiveEditorView();
14429
- if (view_47) setTableProperties(props_0)(view_47.state, view_47.dispatch);
14689
+ const view_48 = getActiveEditorView();
14690
+ if (view_48) setTableProperties(props_0)(view_48.state, view_48.dispatch);
14430
14691
  }, [getActiveEditorView]);
14431
14692
  const closeImagePosition = useCallback(() => setImagePositionOpen(false), [setImagePositionOpen]);
14432
14693
  const closeImageProperties = useCallback(() => setImagePropsOpen(false), [setImagePropsOpen]);
@@ -14434,8 +14695,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14434
14695
  const closeFootnoteProperties = useCallback(() => setFootnotePropsOpen(false), []);
14435
14696
  const closeInsertSymbol = useCallback(() => setShowInsertSymbol(false), []);
14436
14697
  const insertSymbol = useCallback((symbol) => {
14437
- const view_48 = getActiveEditorView();
14438
- if (view_48) view_48.dispatch(view_48.state.tr.insertText(symbol).scrollIntoView());
14698
+ const view_49 = getActiveEditorView();
14699
+ if (view_49) view_49.dispatch(view_49.state.tr.insertText(symbol).scrollIntoView());
14439
14700
  }, [getActiveEditorView]);
14440
14701
  const imagePropertiesCurrentData = useMemo(() => buildImagePropertiesData(state.pmImageContext), [state.pmImageContext]);
14441
14702
  const currentFindResult = findResultRef.current;
@@ -14602,8 +14863,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14602
14863
  onFormat: handleFormat,
14603
14864
  onUndo: undoActiveEditor,
14604
14865
  onRedo: redoActiveEditor,
14605
- canUndo: hfEditPosition ? history.canUndo : bodyHistoryAvailability.canUndo,
14606
- canRedo: hfEditPosition ? history.canRedo : bodyHistoryAvailability.canRedo,
14866
+ canUndo: activeHistoryAvailability.canUndo,
14867
+ canRedo: activeHistoryAvailability.canRedo,
14607
14868
  disabled: readOnly,
14608
14869
  theme: history.state.package.theme || theme || null,
14609
14870
  fontFamilies,
@@ -14726,13 +14987,22 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14726
14987
  firstPageHeaderContentRId: activeFirstHeaderRId,
14727
14988
  firstPageFooterContentRId: activeFirstFooterRId,
14728
14989
  ...history.state.package.styles ? { styles: history.state.package.styles } : {},
14729
- onHeaderFooterDoubleClick: showHeaderFooterEditing ? handleHeaderFooterDoubleClick : void 0,
14990
+ onHeaderFooterDoubleClick: showHeaderFooterEditing ? handleHeaderFooterStoryOpen : void 0,
14730
14991
  hfEditMode: hfEditPosition,
14992
+ activeHeaderFooterRId: activeHfRId,
14731
14993
  onBodyClick: handleBodyClick,
14994
+ onActiveNoteStoryChange: handleActiveNoteStoryChange,
14732
14995
  zoom,
14996
+ showMarginGuides,
14997
+ ...marginGuideColor !== void 0 ? { marginGuideColor } : {},
14733
14998
  readOnly,
14734
14999
  onDocumentChange: handleDocumentChange,
14735
15000
  extensionManager,
15001
+ suggestionModeActive: editingMode === "suggesting",
15002
+ suggestionAuthor: author,
15003
+ ...onCopy !== void 0 ? { onCopy } : {},
15004
+ ...onCut !== void 0 ? { onCut } : {},
15005
+ ...onPaste !== void 0 ? { onPaste } : {},
14736
15006
  ...onReadonlyEditAttempt !== void 0 ? { onReadOnlyEditAttempt: onReadonlyEditAttempt } : {},
14737
15007
  onSelectionChange: handlePagedSelectionChange,
14738
15008
  ...onSelectionTextChange !== void 0 ? { onSelectionTextChange } : {},
@@ -14761,8 +15031,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14761
15031
  onMouseDown: (e_1) => {
14762
15032
  e_1.preventDefault();
14763
15033
  e_1.stopPropagation();
14764
- const view_49 = pagedEditorRef.current?.getView();
14765
- if (!view_49) {
15034
+ const view_50 = pagedEditorRef.current?.getView();
15035
+ if (!view_50) {
14766
15036
  setFloatingCommentBtn(null);
14767
15037
  return;
14768
15038
  }
@@ -14770,9 +15040,9 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14770
15040
  from: floatingCommentBtn.from,
14771
15041
  to: floatingCommentBtn.to
14772
15042
  };
14773
- const currentSelection = view_49.state.selection;
15043
+ const currentSelection = view_50.state.selection;
14774
15044
  const safeRange = resolveCommentCreationRange({
14775
- docSize: view_49.state.doc.content.size,
15045
+ docSize: view_50.state.doc.content.size,
14776
15046
  capturedRange,
14777
15047
  currentRange: {
14778
15048
  from: currentSelection.from,
@@ -14786,7 +15056,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14786
15056
  return;
14787
15057
  }
14788
15058
  setCommentSelectionRange(safeRange);
14789
- if (!applyCommentMarkRange(view_49, safeRange, -1, { selectEnd: true })) {
15059
+ if (!applyCommentMarkRange(view_50, safeRange, -1, { selectEnd: true })) {
14790
15060
  setCommentSelectionRange(null);
14791
15061
  setFloatingCommentBtn(null);
14792
15062
  return;
@@ -14916,7 +15186,10 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14916
15186
  onClose: handleContextMenuClose
14917
15187
  })
14918
15188
  }),
14919
- /* @__PURE__ */ jsx(ContentControlWidgetsOverlay, { getEditorView: getBodyEditorView }),
15189
+ /* @__PURE__ */ jsx(ContentControlWidgetsOverlay, {
15190
+ getEventRoot: getContentControlEventRoot,
15191
+ getEditorView: getBodyEditorView
15192
+ }),
14920
15193
  /* @__PURE__ */ jsx(DocxEditorDialogs, {
14921
15194
  findReplace: findReplaceDialog,
14922
15195
  tableProperties: tablePropertiesDialog,