@stll/folio-react 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ import { normalizeBaseDirection } from "@stll/folio-core/docx/normalizeBaseDirec
12
12
  import { getCachedNumberingMap } from "@stll/folio-core/docx/numberingParser";
13
13
  import { computeScrollPageInfo, updateScrollPageTotal } from "@stll/folio-core/paged-layout/scrollPageInfo";
14
14
  import { TextSelection, addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, captureFormatMarks, clearFormatting, clearTextColor, createStyleResolver, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, extractSelectionState, getSelectedText, getTableContext, increaseIndent, increaseListLevel, mergeCells, removeTabStop, removeTableBorders, schema, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableProperties, setTextColor, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline } from "@stll/folio-core/prosemirror";
15
- import { acceptAIEditRevision, acceptChange, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, rejectAIEditRevision, rejectChange } from "@stll/folio-core/prosemirror/commands/comments";
15
+ import { acceptAIEditRevision, acceptChange, acceptSuggestion, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectChange, rejectSuggestion } from "@stll/folio-core/prosemirror/commands/comments";
16
16
  import { blockSdtAttrsToSdtProperties, findBlockSdtMatch, findBlockSdtMatches, removeContentControlTr, setContentControlContentTr, setContentControlValueTr } from "@stll/folio-core/prosemirror/commands/contentControls";
17
17
  import { setContentControlContentBlocksTr } from "@stll/folio-core/prosemirror/commands/contentControlsBlockFill";
18
18
  import { CLIPBOARD_READ_ERROR_EVENT, buildPlainTextSlice } from "@stll/folio-core/prosemirror/commands/pastePlainText";
@@ -59,6 +59,7 @@ import { findNoteStoryForTarget } from "@stll/folio-core/layout-bridge/dom/noteS
59
59
  import { clickToPosition } from "@stll/folio-core/layout-bridge/engine/clickToPosition";
60
60
  import { getPageTop, hitTestFragment, hitTestTableCell } from "@stll/folio-core/layout-bridge/engine/hitTest";
61
61
  import { clearAllCaches, resetCanvasContext } from "@stll/folio-core/layout-bridge/engine/measuring";
62
+ import { setEmbeddedFontFamilyMap } from "@stll/folio-core/utils/fontResolver";
62
63
  import { resolveSectionHeaderFooterRefs } from "@stll/folio-core/layout-engine";
63
64
  import { recordLayoutPhase } from "@stll/folio-core/layout-engine/layoutInstrumentation";
64
65
  import { LayoutPainter } from "@stll/folio-core/layout-painter";
@@ -75,7 +76,7 @@ import { tableInsertButtonOffset } from "@stll/folio-core/paged-layout/tableInse
75
76
  import { getTransactionDirtyRange } from "@stll/folio-core/paged-layout/transactionDirtyRange";
76
77
  import { findStartPosForParaId } from "@stll/folio-core/prosemirror/utils/findParagraphByParaId";
77
78
  import { expectImageAttrs, expectTableAttrs, expectTableCellAttrs, mergeImageAttrs, mergeTableAttrs, mergeTableCellAttrs, mergeTableRowAttrs } from "@stll/folio-core/prosemirror/attrs";
78
- import { extractEmbeddedFonts } from "@stll/folio-core/fonts/embeddedFonts";
79
+ import { buildEmbeddedFontFamilyMap, extractEmbeddedFonts } from "@stll/folio-core/fonts/embeddedFonts";
79
80
  import { panic } from "better-result";
80
81
  import { collectRemoteSelections, createHiddenEditorManager, createHiddenEditorState } from "@stll/folio-core/controller/hiddenEditorManager";
81
82
  import { loadCollaborationModules } from "@stll/folio-core/controller/collaborationModules";
@@ -97,6 +98,7 @@ import { applyImagePosition, applyImageProperties, applyImageTransform, applyIma
97
98
  import { classifyEditorKeydown, deleteSelectedTable, isFocusInInputLike, isMacPlatform } from "@stll/folio-core/managers/editorShortcuts";
98
99
  import { getScrollTopForZoomAnchor, getViewportCenterZoomAnchorForZoomChange } from "@stll/folio-core/paged-layout/zoomScrollAnchor";
99
100
  import { ZOOM_MAX, ZOOM_MIN, ZOOM_STEP } from "@stll/folio-core/utils/zoom";
101
+ import { isValidHexId } from "@stll/folio-core/utils/hexId";
100
102
  import { createRoot } from "react-dom/client";
101
103
  //#region src/hooks/useHistory.ts
102
104
  /**
@@ -1005,6 +1007,10 @@ function _temp$9(rect, idx) {
1005
1007
  * `FontFace` handles so the caller can remove them on document change/unmount,
1006
1008
  * preventing one document's embedded family from bleeding into the next.
1007
1009
  */
1010
+ const EMPTY_LOADED_EMBEDDED_FONTS = {
1011
+ faces: [],
1012
+ familyMap: /* @__PURE__ */ new Map()
1013
+ };
1008
1014
  function getDocumentFontSet$1() {
1009
1015
  if (typeof document === "undefined" || !("fonts" in document)) return null;
1010
1016
  return document.fonts;
@@ -1037,14 +1043,14 @@ async function registerFontFace(fontSet, family, source, descriptors) {
1037
1043
  */
1038
1044
  async function loadEmbeddedFontFaces(buffer) {
1039
1045
  const fontSet = getDocumentFontSet$1();
1040
- if (!fontSet) return [];
1046
+ if (!fontSet) return EMPTY_LOADED_EMBEDDED_FONTS;
1041
1047
  let fonts;
1042
1048
  try {
1043
1049
  fonts = await extractEmbeddedFonts(buffer);
1044
1050
  } catch {
1045
- return [];
1051
+ return EMPTY_LOADED_EMBEDDED_FONTS;
1046
1052
  }
1047
- if (fonts.length === 0) return [];
1053
+ if (fonts.length === 0) return EMPTY_LOADED_EMBEDDED_FONTS;
1048
1054
  const loaded = [];
1049
1055
  await Promise.all(fonts.map(async (font) => {
1050
1056
  const face = await registerFontFace(fontSet, font.family, font.bytes, {
@@ -1053,7 +1059,10 @@ async function loadEmbeddedFontFaces(buffer) {
1053
1059
  });
1054
1060
  if (face) loaded.push(face);
1055
1061
  }));
1056
- return loaded;
1062
+ return {
1063
+ faces: loaded,
1064
+ familyMap: buildEmbeddedFontFamilyMap(fonts)
1065
+ };
1057
1066
  }
1058
1067
  /** Remove previously registered faces from the document font set. */
1059
1068
  function removeFontFaces(faces) {
@@ -4341,7 +4350,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
4341
4350
  e.preventDefault();
4342
4351
  return;
4343
4352
  }
4344
- if (e.button !== 0) return;
4353
+ if (e.button !== 0) {
4354
+ if ((e.target instanceof HTMLElement ? e.target : null)?.closest("a[href]") instanceof HTMLAnchorElement) e.preventDefault();
4355
+ return;
4356
+ }
4345
4357
  setTableInsertButton(null);
4346
4358
  clearTableInsertTimer();
4347
4359
  const target_1 = e.target instanceof HTMLElement ? e.target : null;
@@ -5572,13 +5584,14 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5572
5584
  if (!embeddedFontBuffer) return;
5573
5585
  let cancelled_1 = false;
5574
5586
  let registered = [];
5575
- loadEmbeddedFontFaces(embeddedFontBuffer).then((faces) => {
5587
+ loadEmbeddedFontFaces(embeddedFontBuffer).then(({ faces, familyMap }) => {
5576
5588
  if (cancelled_1) {
5577
5589
  removeFontFaces(faces);
5578
5590
  return;
5579
5591
  }
5580
5592
  registered = faces;
5581
- if (faces.length === 0) return;
5593
+ if (faces.length === 0 && familyMap.size === 0) return;
5594
+ setEmbeddedFontFamilyMap(familyMap.size > 0 ? familyMap : null);
5582
5595
  const view_23 = hiddenPMRef.current?.getView();
5583
5596
  if (!view_23) return;
5584
5597
  resetCanvasContext();
@@ -5589,6 +5602,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
5589
5602
  return () => {
5590
5603
  cancelled_1 = true;
5591
5604
  removeFontFaces(registered);
5605
+ setEmbeddedFontFamilyMap(null);
5592
5606
  };
5593
5607
  }, [embeddedFontBuffer]);
5594
5608
  useEffect(() => {
@@ -12186,13 +12200,52 @@ const getBuiltinTableStyle = (styleId) => BUILTIN_STYLES.find((s) => s.id === st
12186
12200
  * (`replaceComments`/`updateComments`) stay in the component because they
12187
12201
  * depend on its document-build pipeline.
12188
12202
  */
12203
+ /**
12204
+ * Sanitize a `paraId`/`textId`-bearing paragraph: drop either field when it
12205
+ * isn't a well-formed OOXML long-hex id (see `isValidHexId`), leaving
12206
+ * everything else untouched. Comment paragraphs from a controlled
12207
+ * `commentsProp` come from the host app rather than our own parser/
12208
+ * serializer, so they aren't guaranteed to satisfy the id shape those trust.
12209
+ */
12210
+ function sanitizeCommentParagraph(paragraph) {
12211
+ const paraIdValid = paragraph.paraId === void 0 || isValidHexId(paragraph.paraId);
12212
+ const textIdValid = paragraph.textId === void 0 || isValidHexId(paragraph.textId);
12213
+ if (paraIdValid && textIdValid) return paragraph;
12214
+ const { paraId, textId, ...rest } = paragraph;
12215
+ return {
12216
+ ...rest,
12217
+ ...paraIdValid && paraId !== void 0 ? { paraId } : {},
12218
+ ...textIdValid && textId !== void 0 ? { textId } : {}
12219
+ };
12220
+ }
12221
+ /**
12222
+ * Validate a controlled `commentsProp` at the boundary before it becomes
12223
+ * editor state. A host app (or a collaboration payload relayed through it)
12224
+ * can hand back arbitrary JSON, so `id` isn't guaranteed numeric and
12225
+ * paragraph `paraId`/`textId` aren't guaranteed to be real Word ids — both
12226
+ * eventually reach XML/CSS-adjacent serialization (comment threading,
12227
+ * `[data-comment-id]` selectors). Comments with a non-finite `id` are
12228
+ * dropped entirely; malformed paraId/textId are stripped in place.
12229
+ */
12230
+ function sanitizeControlledComments(comments) {
12231
+ const sanitized = [];
12232
+ for (const comment of comments) {
12233
+ if (!Number.isFinite(comment.id)) continue;
12234
+ sanitized.push({
12235
+ ...comment,
12236
+ content: comment.content.map(sanitizeCommentParagraph)
12237
+ });
12238
+ }
12239
+ return sanitized;
12240
+ }
12189
12241
  function useFolioComments({ doc, autoOpenReviewSidebar, anchorPositions, editorContentRef, commentsProp, onCommentsChange }) {
12190
12242
  const [showCommentsSidebar, setShowCommentsSidebar] = useState(false);
12191
12243
  const [visibleCommentAuthors, setVisibleCommentAuthors] = useState(null);
12192
12244
  const [activeCommentId, setActiveCommentId] = useState(null);
12193
12245
  const [internalComments, setInternalComments] = useState([]);
12194
- const isControlledComments = commentsProp !== void 0;
12195
- const comments = isControlledComments ? commentsProp : internalComments;
12246
+ const sanitizedCommentsProp = useMemo(() => commentsProp !== void 0 ? sanitizeControlledComments(commentsProp) : void 0, [commentsProp]);
12247
+ const isControlledComments = sanitizedCommentsProp !== void 0;
12248
+ const comments = isControlledComments ? sanitizedCommentsProp : internalComments;
12196
12249
  const commentsDirtyRef = useRef(false);
12197
12250
  const commentsRef = useRef(comments);
12198
12251
  commentsRef.current = comments;
@@ -12347,7 +12400,7 @@ function useFolioComments({ doc, autoOpenReviewSidebar, anchorPositions, editorC
12347
12400
  * - Error boundary
12348
12401
  * - Loading states
12349
12402
  */
12350
- const CommentsSidebar = lazy(() => import("./CommentsSidebar-ml91aGZ1.js").then((m) => ({ default: m.CommentsSidebar })));
12403
+ const CommentsSidebar = lazy(() => import("./CommentsSidebar-mwa9JsIj.js").then((m) => ({ default: m.CommentsSidebar })));
12351
12404
  const TextContextMenu = lazy(() => import("./TextContextMenu-Ci7-M4oU.js").then((m) => ({ default: m.TextContextMenu })));
12352
12405
  const loadAttemptSelectiveSave = async () => {
12353
12406
  const { attemptSelectiveSave } = await import("@stll/folio-core/docx/selectiveSave");
@@ -12445,6 +12498,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12445
12498
  showOutlineRef.current = showOutline;
12446
12499
  const [outlineHeadings, setHeadingInfos] = useState([]);
12447
12500
  const [, setTrackedChanges] = useState([]);
12501
+ const trackedChangesRef = useRef([]);
12448
12502
  const [anchorPositions, setAnchorPositions] = useState(EMPTY_ANCHOR_POSITIONS);
12449
12503
  const { editingMode, readOnly, trackChangesOn, toggleTrackChanges, displayMode, setDisplayMode } = useEditorMode({
12450
12504
  modeProp,
@@ -12484,6 +12538,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
12484
12538
  last.to = entry_0.to;
12485
12539
  } else merged.push({ ...entry_0 });
12486
12540
  }
12541
+ trackedChangesRef.current = merged;
12487
12542
  setTrackedChanges(merged);
12488
12543
  }, []);
12489
12544
  useEffect(() => () => {
@@ -14012,7 +14067,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14012
14067
  undoHandle,
14013
14068
  reason: "documentChanged"
14014
14069
  };
14015
- if (!(pagedEditorRef.current?.undo() ?? false)) return {
14070
+ if (!undo(view_21.state, view_21.dispatch)) return {
14016
14071
  status: "rejected",
14017
14072
  undoHandle,
14018
14073
  reason: "documentChanged"
@@ -14169,82 +14224,118 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14169
14224
  });
14170
14225
  return true;
14171
14226
  },
14172
- getTrackedChanges: () => {
14227
+ getSuggestions: () => {
14173
14228
  const view_29 = pagedEditorRef.current?.getView();
14174
- return view_29 ? getTrackedChangesFromDoc(view_29.state.doc) : [];
14229
+ return view_29 ? getSuggestions(view_29.state) : [];
14175
14230
  },
14176
- getCommentAnchors: () => {
14231
+ acceptSuggestion: (suggestionId, options_2) => {
14177
14232
  const view_30 = pagedEditorRef.current?.getView();
14178
- return view_30 ? getCommentAnchorsFromDoc(view_30.state.doc) : [];
14233
+ if (!view_30) return {
14234
+ accepted: false,
14235
+ appliedAs: null
14236
+ };
14237
+ const appliedAs = getSuggestions(view_30.state).find((s_0) => s_0.suggestionId === suggestionId)?.appliedAs ?? null;
14238
+ const accepted = acceptSuggestion(suggestionId, { author: options_2?.author ?? author })(view_30.state, view_30.dispatch);
14239
+ return {
14240
+ accepted,
14241
+ appliedAs: accepted ? appliedAs : null
14242
+ };
14179
14243
  },
14180
- getSelectionText: () => {
14244
+ rejectSuggestion: (suggestionId_0) => {
14181
14245
  const view_31 = pagedEditorRef.current?.getView();
14182
- return view_31 ? getSelectedText(view_31.state) : "";
14246
+ if (!view_31) return false;
14247
+ return rejectSuggestion(suggestionId_0)(view_31.state, view_31.dispatch);
14183
14248
  },
14184
- getPageText: (page_0) => {
14249
+ scrollToSuggestion: (suggestionId_1) => {
14185
14250
  const view_32 = pagedEditorRef.current?.getView();
14186
- if (!view_32) return null;
14187
- return getPageTextFromLayout(pagedEditorRef.current?.getEditor()?.getLayout() ?? null, view_32.state.doc, page_0);
14251
+ if (!view_32) return false;
14252
+ const range_5 = findSuggestionRange(view_32.state, suggestionId_1);
14253
+ if (!range_5) return false;
14254
+ const { from: from_12, to: to_12 } = clampRangeToDocSize(view_32.state.doc.content.size, range_5);
14255
+ const $from_3 = view_32.state.doc.resolve(from_12);
14256
+ const $to_3 = view_32.state.doc.resolve(to_12);
14257
+ view_32.dispatch(view_32.state.tr.setSelection(TextSelection.between($from_3, $to_3)));
14258
+ requestAnimationFrame(() => {
14259
+ pagedEditorRef.current?.scrollToPosition(from_12);
14260
+ });
14261
+ return true;
14188
14262
  },
14189
- getTargetPage: (target_2, snapshot_4) => {
14263
+ getTrackedChanges: () => {
14190
14264
  const view_33 = pagedEditorRef.current?.getView();
14191
- if (!view_33) return null;
14192
- const range_5 = target_2.type === "textRange" ? resolveFolioAITextRange({
14265
+ return view_33 ? getTrackedChangesFromDoc(view_33.state.doc) : [];
14266
+ },
14267
+ getCommentAnchors: () => {
14268
+ const view_34 = pagedEditorRef.current?.getView();
14269
+ return view_34 ? getCommentAnchorsFromDoc(view_34.state.doc) : [];
14270
+ },
14271
+ getSelectionText: () => {
14272
+ const view_35 = pagedEditorRef.current?.getView();
14273
+ return view_35 ? getSelectedText(view_35.state) : "";
14274
+ },
14275
+ getPageText: (page_0) => {
14276
+ const view_36 = pagedEditorRef.current?.getView();
14277
+ if (!view_36) return null;
14278
+ return getPageTextFromLayout(pagedEditorRef.current?.getEditor()?.getLayout() ?? null, view_36.state.doc, page_0);
14279
+ },
14280
+ getTargetPage: (target_2, snapshot_4) => {
14281
+ const view_37 = pagedEditorRef.current?.getView();
14282
+ if (!view_37) return null;
14283
+ const range_6 = target_2.type === "textRange" ? resolveFolioAITextRange({
14193
14284
  range: target_2,
14194
- doc: view_33.state.doc,
14285
+ doc: view_37.state.doc,
14195
14286
  snapshot: snapshot_4
14196
14287
  }) : resolveFolioAIBlockRange({
14197
14288
  blockId: target_2.blockId,
14198
- doc: view_33.state.doc,
14289
+ doc: view_37.state.doc,
14199
14290
  snapshot: snapshot_4
14200
14291
  });
14201
- if (range_5 === null) return null;
14202
- return pagedEditorRef.current?.getPageNumberForPmPos(range_5.from) ?? null;
14292
+ if (range_6 === null) return null;
14293
+ return pagedEditorRef.current?.getPageNumberForPmPos(range_6.from) ?? null;
14203
14294
  },
14204
14295
  getContentControls: (filter = {}) => {
14205
- const view_34 = pagedEditorRef.current?.getView();
14206
- if (!view_34) return [];
14207
- return findBlockSdtMatches(view_34.state.doc, filter).map((match_0) => ({
14296
+ const view_38 = pagedEditorRef.current?.getView();
14297
+ if (!view_38) return [];
14298
+ return findBlockSdtMatches(view_38.state.doc, filter).map((match_0) => ({
14208
14299
  properties: blockSdtAttrsToSdtProperties(match_0.node),
14209
14300
  path: match_0.path,
14210
14301
  pmPos: match_0.pos
14211
14302
  }));
14212
14303
  },
14213
14304
  scrollToContentControl: (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);
14305
+ const view_39 = pagedEditorRef.current?.getView();
14306
+ if (!view_39) return false;
14307
+ const match_1 = findBlockSdtMatch(view_39.state.doc, filter_0);
14217
14308
  if (!match_1) return false;
14218
14309
  const inside = match_1.pos + 1;
14219
- const $pos = view_35.state.doc.resolve(inside);
14220
- view_35.dispatch(view_35.state.tr.setSelection(TextSelection.near($pos)));
14310
+ const $pos = view_39.state.doc.resolve(inside);
14311
+ view_39.dispatch(view_39.state.tr.setSelection(TextSelection.near($pos)));
14221
14312
  requestAnimationFrame(() => {
14222
14313
  pagedEditorRef.current?.scrollToPosition(inside);
14223
14314
  });
14224
14315
  return true;
14225
14316
  },
14226
- setContentControlContent: (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);
14317
+ setContentControlContent: (filter_1, input, options_3 = {}) => {
14318
+ const view_40 = pagedEditorRef.current?.getView();
14319
+ if (!view_40) return false;
14320
+ const tr_0 = typeof input === "string" ? setContentControlContentTr(view_40.state, filter_1, input, options_3) : setContentControlContentBlocksTr(view_40.state, filter_1, input, options_3);
14230
14321
  if (!tr_0) return false;
14231
- view_36.dispatch(tr_0);
14322
+ view_40.dispatch(tr_0);
14232
14323
  return true;
14233
14324
  },
14234
- setContentControlValue: (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);
14325
+ setContentControlValue: (filter_2, input_0, options_4 = {}) => {
14326
+ const view_41 = pagedEditorRef.current?.getView();
14327
+ if (!view_41) return false;
14328
+ const tr_1 = setContentControlValueTr(view_41.state, filter_2, input_0, options_4);
14238
14329
  if (!tr_1) return false;
14239
- view_37.dispatch(tr_1);
14330
+ view_41.dispatch(tr_1);
14240
14331
  return true;
14241
14332
  },
14242
- removeContentControl: (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);
14333
+ removeContentControl: (filter_3, options_5 = {}) => {
14334
+ const view_42 = pagedEditorRef.current?.getView();
14335
+ if (!view_42) return false;
14336
+ const tr_2 = removeContentControlTr(view_42.state, filter_3, options_5);
14246
14337
  if (!tr_2) return false;
14247
- view_38.dispatch(tr_2);
14338
+ view_42.dispatch(tr_2);
14248
14339
  return true;
14249
14340
  }
14250
14341
  }), [
@@ -14326,39 +14417,39 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14326
14417
  if (isDisplayMode(value)) setDisplayMode(value);
14327
14418
  }, [setDisplayMode]);
14328
14419
  const handleAcceptActiveChange = useCallback(() => {
14329
- const view_39 = pagedEditorRef.current?.getView();
14330
- if (!view_39) return;
14331
- const { from: from_12, to: to_12 } = view_39.state.selection;
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);
14420
+ const view_43 = pagedEditorRef.current?.getView();
14421
+ if (!view_43) return;
14422
+ const { from: from_13, to: to_13 } = view_43.state.selection;
14423
+ const range_7 = findChangeAtPosition(view_43.state, from_13, to_13);
14424
+ acceptChange(range_7.from, range_7.to)(view_43.state, view_43.dispatch);
14334
14425
  }, []);
14335
14426
  const handleRejectActiveChange = useCallback(() => {
14336
- const view_40 = pagedEditorRef.current?.getView();
14337
- if (!view_40) return;
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);
14427
+ const view_44 = pagedEditorRef.current?.getView();
14428
+ if (!view_44) return;
14429
+ const { from: from_14, to: to_14 } = view_44.state.selection;
14430
+ const range_8 = findChangeAtPosition(view_44.state, from_14, to_14);
14431
+ rejectChange(range_8.from, range_8.to)(view_44.state, view_44.dispatch);
14341
14432
  }, []);
14342
14433
  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);
14434
+ const view_45 = pagedEditorRef.current?.getView();
14435
+ if (!view_45) return;
14436
+ const { from: from_15 } = view_45.state.selection;
14437
+ const change = findPreviousChange(view_45.state, from_15);
14347
14438
  if (!change) return;
14348
- view_41.dispatch(view_41.state.tr.setSelection(TextSelection.create(view_41.state.doc, change.from, change.to)));
14349
- view_41.focus();
14439
+ view_45.dispatch(view_45.state.tr.setSelection(TextSelection.create(view_45.state.doc, change.from, change.to)));
14440
+ view_45.focus();
14350
14441
  requestAnimationFrame(() => {
14351
14442
  pagedEditorRef.current?.scrollToPosition(change.from);
14352
14443
  });
14353
14444
  }, []);
14354
14445
  const handleNextChange = useCallback(() => {
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);
14446
+ const view_46 = pagedEditorRef.current?.getView();
14447
+ if (!view_46) return;
14448
+ const { to: to_15 } = view_46.state.selection;
14449
+ const change_0 = findNextChange(view_46.state, to_15);
14359
14450
  if (!change_0) return;
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();
14451
+ view_46.dispatch(view_46.state.tr.setSelection(TextSelection.create(view_46.state.doc, change_0.from, change_0.to)));
14452
+ view_46.focus();
14362
14453
  requestAnimationFrame(() => {
14363
14454
  pagedEditorRef.current?.scrollToPosition(change_0.from);
14364
14455
  });
@@ -14528,8 +14619,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14528
14619
  requestAnimationFrame(syncCommentHighlightStyles);
14529
14620
  }, [onScrollTopChange, syncCommentHighlightStyles]);
14530
14621
  const handlePagedSelectionChange = useCallback((_from, _to) => {
14531
- const view_43 = getActiveEditorView() ?? pagedEditorRef.current?.getView() ?? null;
14532
- handleSelectionChange(view_43 ? extractSelectionState(view_43.state) : null);
14622
+ const view_47 = getActiveEditorView() ?? pagedEditorRef.current?.getView() ?? null;
14623
+ handleSelectionChange(view_47 ? extractSelectionState(view_47.state) : null);
14533
14624
  }, [getActiveEditorView, handleSelectionChange]);
14534
14625
  const handleTotalPagesChange = useCallback((totalPages) => {
14535
14626
  setScrollPageInfo((previous) => updateScrollPageTotal(previous, totalPages));
@@ -14554,9 +14645,9 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14554
14645
  }, [author, updateComments]);
14555
14646
  const handleAddComment = useCallback((addText) => {
14556
14647
  const comment_3 = createComment(addText, author);
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;
14648
+ const view_48 = pagedEditorRef.current?.getView();
14649
+ if (!view_48 || !commentSelectionRange) return false;
14650
+ if (!applyCommentMarkRange(view_48, commentSelectionRange, comment_3.id, { replacePending: true })) return false;
14560
14651
  const commentAuthor_2 = getCommentAuthorKey(comment_3.author);
14561
14652
  setVisibleCommentAuthors((current) => {
14562
14653
  if (current === null) return null;
@@ -14590,8 +14681,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14590
14681
  updateComments((previous_4) => [...previous_4, createComment(text_7, author, revisionId_2)]);
14591
14682
  }, [author, updateComments]);
14592
14683
  const handleCancelAddComment = useCallback(() => {
14593
- const view_45 = pagedEditorRef.current?.getView();
14594
- if (view_45 && commentSelectionRange) removePendingCommentMarkRange(view_45, commentSelectionRange);
14684
+ const view_49 = pagedEditorRef.current?.getView();
14685
+ if (view_49 && commentSelectionRange) removePendingCommentMarkRange(view_49, commentSelectionRange);
14595
14686
  setIsAddingComment(false);
14596
14687
  setCommentSelectionRange(null);
14597
14688
  setAddCommentYPosition(null);
@@ -14601,18 +14692,27 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14601
14692
  setCommentSelectionRange,
14602
14693
  setIsAddingComment
14603
14694
  ]);
14604
- const handleSidebarAcceptChange = useCallback((from_15, to_15) => {
14605
- const view_46 = pagedEditorRef.current?.getView();
14606
- if (!view_46) return;
14607
- acceptChange(from_15, to_15)(view_46.state, view_46.dispatch);
14695
+ const resolveSidebarChangeRevisionId = useCallback((from_16, to_16) => {
14696
+ return trackedChangesRef.current.find((candidate) => {
14697
+ return candidate.from === from_16 && candidate.to === to_16;
14698
+ })?.revisionId ?? null;
14699
+ }, []);
14700
+ const handleSidebarAcceptChange = useCallback((from_17, to_17) => {
14701
+ const view_50 = pagedEditorRef.current?.getView();
14702
+ if (!view_50) return;
14703
+ const revisionId_3 = resolveSidebarChangeRevisionId(from_17, to_17);
14704
+ if (revisionId_3 === null) return;
14705
+ acceptAIEditRevision(revisionId_3)(view_50.state, view_50.dispatch);
14608
14706
  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);
14707
+ }, [extractTrackedChanges, resolveSidebarChangeRevisionId]);
14708
+ const handleSidebarRejectChange = useCallback((from_18, to_18) => {
14709
+ const view_51 = pagedEditorRef.current?.getView();
14710
+ if (!view_51) return;
14711
+ const revisionId_4 = resolveSidebarChangeRevisionId(from_18, to_18);
14712
+ if (revisionId_4 === null) return;
14713
+ rejectAIEditRevision(revisionId_4)(view_51.state, view_51.dispatch);
14614
14714
  extractTrackedChanges();
14615
- }, [extractTrackedChanges]);
14715
+ }, [extractTrackedChanges, resolveSidebarChangeRevisionId]);
14616
14716
  const commentsPageWidth = history.state?.package.document.finalSectionProperties?.pageWidth;
14617
14717
  const commentsSidebarOverlay = useMemo(() => {
14618
14718
  if (!showCommentsSidebar) return;
@@ -14686,8 +14786,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14686
14786
  }, [readOnly]);
14687
14787
  const closeTableProperties = useCallback(() => setTablePropsOpen(false), []);
14688
14788
  const applyTableProperties = useCallback((props_0) => {
14689
- const view_48 = getActiveEditorView();
14690
- if (view_48) setTableProperties(props_0)(view_48.state, view_48.dispatch);
14789
+ const view_52 = getActiveEditorView();
14790
+ if (view_52) setTableProperties(props_0)(view_52.state, view_52.dispatch);
14691
14791
  }, [getActiveEditorView]);
14692
14792
  const closeImagePosition = useCallback(() => setImagePositionOpen(false), [setImagePositionOpen]);
14693
14793
  const closeImageProperties = useCallback(() => setImagePropsOpen(false), [setImagePropsOpen]);
@@ -14695,8 +14795,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
14695
14795
  const closeFootnoteProperties = useCallback(() => setFootnotePropsOpen(false), []);
14696
14796
  const closeInsertSymbol = useCallback(() => setShowInsertSymbol(false), []);
14697
14797
  const insertSymbol = useCallback((symbol) => {
14698
- const view_49 = getActiveEditorView();
14699
- if (view_49) view_49.dispatch(view_49.state.tr.insertText(symbol).scrollIntoView());
14798
+ const view_53 = getActiveEditorView();
14799
+ if (view_53) view_53.dispatch(view_53.state.tr.insertText(symbol).scrollIntoView());
14700
14800
  }, [getActiveEditorView]);
14701
14801
  const imagePropertiesCurrentData = useMemo(() => buildImagePropertiesData(state.pmImageContext), [state.pmImageContext]);
14702
14802
  const currentFindResult = findResultRef.current;
@@ -15031,8 +15131,8 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
15031
15131
  onMouseDown: (e_1) => {
15032
15132
  e_1.preventDefault();
15033
15133
  e_1.stopPropagation();
15034
- const view_50 = pagedEditorRef.current?.getView();
15035
- if (!view_50) {
15134
+ const view_54 = pagedEditorRef.current?.getView();
15135
+ if (!view_54) {
15036
15136
  setFloatingCommentBtn(null);
15037
15137
  return;
15038
15138
  }
@@ -15040,9 +15140,9 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
15040
15140
  from: floatingCommentBtn.from,
15041
15141
  to: floatingCommentBtn.to
15042
15142
  };
15043
- const currentSelection = view_50.state.selection;
15143
+ const currentSelection = view_54.state.selection;
15044
15144
  const safeRange = resolveCommentCreationRange({
15045
- docSize: view_50.state.doc.content.size,
15145
+ docSize: view_54.state.doc.content.size,
15046
15146
  capturedRange,
15047
15147
  currentRange: {
15048
15148
  from: currentSelection.from,
@@ -15056,7 +15156,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
15056
15156
  return;
15057
15157
  }
15058
15158
  setCommentSelectionRange(safeRange);
15059
- if (!applyCommentMarkRange(view_50, safeRange, -1, { selectEnd: true })) {
15159
+ if (!applyCommentMarkRange(view_54, safeRange, -1, { selectEnd: true })) {
15060
15160
  setCommentSelectionRange(null);
15061
15161
  setFloatingCommentBtn(null);
15062
15162
  return;