@extend-ai/react-docx 0.7.1 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4581,10 +4581,13 @@ var BASE_DOC_STYLE = {
4581
4581
  transition: "box-shadow 0.2s ease"
4582
4582
  };
4583
4583
  var TRACKED_CHANGE_GUTTER_WIDTH_PX = 300;
4584
- var TRACKED_CHANGE_GUTTER_CARD_LEFT_PX = 28;
4585
- var TRACKED_CHANGE_GUTTER_CARD_RIGHT_PX = 10;
4586
- var TRACKED_CHANGE_GUTTER_CARD_GAP_PX = 8;
4587
- var TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX = 52;
4584
+ var TRACKED_CHANGE_GUTTER_CARD_LEFT_PX = 48;
4585
+ var TRACKED_CHANGE_GUTTER_CARD_RIGHT_PX = 12;
4586
+ var TRACKED_CHANGE_GUTTER_CARD_GAP_PX = 4;
4587
+ var TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX = 30;
4588
+ var TRACKED_CHANGE_GUTTER_BEND_OFFSET_PX = 8;
4589
+ var TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_GAP_PX = 7;
4590
+ var TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_COUNT = 5;
4588
4591
  var INITIAL_PAGINATION_STABILITY_IDLE_MS = 240;
4589
4592
  function scheduleDomWrite(callback) {
4590
4593
  if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
@@ -12997,9 +13000,10 @@ function trackedInlineStyle(baseStyle, change) {
12997
13000
  return baseStyle;
12998
13001
  }
12999
13002
  if (change.kind === "insertion" || change.kind === "move-to") {
13003
+ const accentColor = change.kind === "move-to" ? "#70ad47" : "#dc2626";
13000
13004
  return {
13001
13005
  ...baseStyle,
13002
- color: "#2563eb",
13006
+ color: accentColor,
13003
13007
  textDecoration: mergeTextDecorations(
13004
13008
  baseStyle.textDecoration,
13005
13009
  "underline"
@@ -14624,11 +14628,22 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14624
14628
  if (!commentIds || commentIds.length === 0) {
14625
14629
  return void 0;
14626
14630
  }
14627
- const accent = commentAccentColor(documentTheme);
14628
- return {
14629
- backgroundColor: documentTheme === "dark" ? "rgba(251, 191, 36, 0.24)" : "rgba(251, 191, 36, 0.3)",
14630
- borderBottom: `2px solid ${accent}`
14631
- };
14631
+ return commentHighlightStyle(documentTheme, commentIds[0]);
14632
+ };
14633
+ const currentAnnotationAttributes = (trackedInlineChange) => {
14634
+ const attributes = {};
14635
+ if (trackedInlineChange) {
14636
+ attributes["data-docx-tracked-change"] = trackedInlineChange.kind;
14637
+ attributes["data-docx-tracked-change-id"] = trackedInlineChange.id;
14638
+ }
14639
+ const commentIds = commentMarkup?.commentIdsByVisibleChildIndex[trackedVisibleChildCursor];
14640
+ if (commentIds && commentIds.length > 0) {
14641
+ attributes["data-docx-comment-ids"] = commentIds.join(" ");
14642
+ if (commentIds.length === 1) {
14643
+ attributes["data-docx-comment-id"] = String(commentIds[0]);
14644
+ }
14645
+ }
14646
+ return attributes;
14632
14647
  };
14633
14648
  const consumeTrackedVisibleChild = (child) => {
14634
14649
  if (!trackedMarkup && !commentMarkup) {
@@ -14662,11 +14677,11 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14662
14677
  fallbackTabWidthPx,
14663
14678
  checkboxChoiceRow
14664
14679
  );
14665
- const appendPlainTextWithSoftBreakControl = (target, keySeed, text, style, measureStyle) => {
14680
+ const appendPlainTextWithSoftBreakControl = (target, keySeed, text, style, measureStyle, spanAttributes) => {
14666
14681
  const shouldControlSoftBreakStretch = paragraph.style?.align === "justify" && text.includes("\n");
14667
14682
  if (!shouldControlSoftBreakStretch) {
14668
14683
  target.push(
14669
- /* @__PURE__ */ jsx("span", { style, children: text }, keySeed)
14684
+ /* @__PURE__ */ jsx("span", { ...spanAttributes, style, children: text }, keySeed)
14670
14685
  );
14671
14686
  trackTextAdvance(text, measureStyle);
14672
14687
  return;
@@ -14682,6 +14697,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14682
14697
  /* @__PURE__ */ jsx(
14683
14698
  "span",
14684
14699
  {
14700
+ ...spanAttributes,
14685
14701
  style: isLastSegment ? {
14686
14702
  ...style,
14687
14703
  display: "inline-block",
@@ -14832,6 +14848,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14832
14848
  " "
14833
14849
  );
14834
14850
  const text = textOverride ?? textValue;
14851
+ const annotationAttributes2 = currentAnnotationAttributes(trackedInlineChange);
14835
14852
  if (child.link) {
14836
14853
  const linkHref = child.link;
14837
14854
  const isInternalLink = linkHref.startsWith("#");
@@ -14839,6 +14856,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14839
14856
  /* @__PURE__ */ jsx(
14840
14857
  "a",
14841
14858
  {
14859
+ ...annotationAttributes2,
14842
14860
  href: linkHref,
14843
14861
  target: isInternalLink ? void 0 : "_blank",
14844
14862
  rel: isInternalLink ? void 0 : "noreferrer noopener",
@@ -14875,12 +14893,20 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14875
14893
  };
14876
14894
  if (text === " " && !useTabLeaderLayout && !useAnchoredTabLayout) {
14877
14895
  target.push(
14878
- /* @__PURE__ */ jsx("span", { style: tabTextStyle(child.style, trackedStyle), children: "\xA0" }, key)
14896
+ /* @__PURE__ */ jsx(
14897
+ "span",
14898
+ {
14899
+ ...annotationAttributes2,
14900
+ style: tabTextStyle(child.style, trackedStyle),
14901
+ children: "\xA0"
14902
+ },
14903
+ key
14904
+ )
14879
14905
  );
14880
14906
  return;
14881
14907
  }
14882
14908
  target.push(
14883
- /* @__PURE__ */ jsx("span", { style: trackedStyle, children: text }, key)
14909
+ /* @__PURE__ */ jsx("span", { ...annotationAttributes2, style: trackedStyle, children: text }, key)
14884
14910
  );
14885
14911
  trackTextAdvance(text, child.style);
14886
14912
  return;
@@ -14949,7 +14975,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14949
14975
  const sectionImageCursor = sectionImageLocation && !sectionImageInteraction?.isReadOnly && !behavesAsDecorativeBehindTextBackground && (isWrappedFloatingImage || isAbsoluteFloatingImage) ? "move" : void 0;
14950
14976
  const isCenteredStandaloneInlineImage = !isWrappedFloatingImage && !isAbsoluteFloatingImage && paragraph.style?.align === "center" && paragraph.children.length === 1 && paragraph.children[0]?.type === "image";
14951
14977
  const trackedImageStyle = trackedInlineChange?.kind === "insertion" || trackedInlineChange?.kind === "move-to" ? {
14952
- outline: "2px solid rgba(37, 99, 235, 0.35)",
14978
+ outline: trackedInlineChange.kind === "move-to" ? "2px solid rgba(112, 173, 71, 0.35)" : "2px solid rgba(220, 38, 38, 0.3)",
14953
14979
  outlineOffset: 1
14954
14980
  } : void 0;
14955
14981
  const renderableImageSrc = syntheticTextBoxSvg(
@@ -15135,6 +15161,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15135
15161
  ),
15136
15162
  ...currentCommentHighlightStyle()
15137
15163
  };
15164
+ const annotationAttributes = currentAnnotationAttributes(trackedInlineChange);
15138
15165
  const noteLabel = noteMarkerLabel(
15139
15166
  child.noteReference,
15140
15167
  safeNoteMarkerIndexes.footnote,
@@ -15145,6 +15172,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15145
15172
  /* @__PURE__ */ jsx(
15146
15173
  "span",
15147
15174
  {
15175
+ ...annotationAttributes,
15148
15176
  style: {
15149
15177
  ...textStyle,
15150
15178
  verticalAlign: "super",
@@ -15160,7 +15188,15 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15160
15188
  }
15161
15189
  if ((textOverride ?? child.text) === " " && !useTabLeaderLayout && !useAnchoredTabLayout) {
15162
15190
  target.push(
15163
- /* @__PURE__ */ jsx("span", { style: tabTextStyle(child.style, textStyle), children: "\xA0" }, key)
15191
+ /* @__PURE__ */ jsx(
15192
+ "span",
15193
+ {
15194
+ ...annotationAttributes,
15195
+ style: tabTextStyle(child.style, textStyle),
15196
+ children: "\xA0"
15197
+ },
15198
+ key
15199
+ )
15164
15200
  );
15165
15201
  return;
15166
15202
  }
@@ -15171,6 +15207,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15171
15207
  /* @__PURE__ */ jsx(
15172
15208
  "a",
15173
15209
  {
15210
+ ...annotationAttributes,
15174
15211
  href: linkHref,
15175
15212
  target: isInternalLink ? void 0 : "_blank",
15176
15213
  rel: isInternalLink ? void 0 : "noreferrer noopener",
@@ -15203,7 +15240,8 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15203
15240
  key,
15204
15241
  textOverride ?? child.text,
15205
15242
  textStyle,
15206
- child.style
15243
+ child.style,
15244
+ annotationAttributes
15207
15245
  );
15208
15246
  };
15209
15247
  const anchoredTabZoneStyle = {
@@ -17914,6 +17952,7 @@ function collectTrackedChangesFromModel(model) {
17914
17952
  trackedMarkup.changes.forEach((change, changeIndex) => {
17915
17953
  trackedChanges.push({
17916
17954
  id: `${paragraphLocationKey(location)}:${change.id}:${changeIndex}`,
17955
+ inlineAnchorId: change.id,
17917
17956
  kind: change.kind,
17918
17957
  author: change.author,
17919
17958
  date: change.date,
@@ -18092,13 +18131,42 @@ function collectCommentsFromModel(model) {
18092
18131
  });
18093
18132
  return comments;
18094
18133
  }
18095
- function commentAccentColor(documentTheme) {
18096
- return documentTheme === "dark" ? "#fbbf24" : "#d97706";
18134
+ function hexColorWithAlpha(color, alpha) {
18135
+ const normalized = color.trim().replace(/^#/, "");
18136
+ if (!/^[\da-f]{6}$/i.test(normalized)) {
18137
+ return color;
18138
+ }
18139
+ const red = Number.parseInt(normalized.slice(0, 2), 16);
18140
+ const green = Number.parseInt(normalized.slice(2, 4), 16);
18141
+ const blue = Number.parseInt(normalized.slice(4, 6), 16);
18142
+ return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
18143
+ }
18144
+ function commentAccentColor(documentTheme, commentId) {
18145
+ const lightPalette = ["#5b9bd5", "#d65f5f", "#8f6ac8", "#70ad47", "#d9872b"];
18146
+ const darkPalette = ["#7dd3fc", "#fca5a5", "#c4b5fd", "#86efac", "#fdba74"];
18147
+ if (Number.isFinite(commentId)) {
18148
+ const palette = documentTheme === "dark" ? darkPalette : lightPalette;
18149
+ return palette[Math.abs(Math.round(commentId)) % palette.length];
18150
+ }
18151
+ return documentTheme === "dark" ? darkPalette[0] : lightPalette[0];
18152
+ }
18153
+ function commentHighlightStyle(documentTheme, commentId) {
18154
+ const accent = commentAccentColor(documentTheme, commentId);
18155
+ return {
18156
+ backgroundColor: hexColorWithAlpha(
18157
+ accent,
18158
+ documentTheme === "dark" ? 0.3 : 0.22
18159
+ ),
18160
+ boxShadow: `inset 0 -1px 0 ${hexColorWithAlpha(
18161
+ accent,
18162
+ documentTheme === "dark" ? 0.7 : 0.48
18163
+ )}`
18164
+ };
18097
18165
  }
18098
18166
  function estimateCommentCardHeight(comment) {
18099
18167
  const snippet = comment.text || "Comment";
18100
- const lines = Math.max(1, Math.ceil(snippet.length / 30));
18101
- return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 34 + lines * 14);
18168
+ const lines = Math.min(2, Math.max(1, Math.ceil(snippet.length / 42)));
18169
+ return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 24 + lines * 11);
18102
18170
  }
18103
18171
  function trackedChangeKindLabel(kind) {
18104
18172
  switch (kind) {
@@ -18120,16 +18188,16 @@ function trackedChangeKindLabel(kind) {
18120
18188
  }
18121
18189
  function trackedChangeAccentColor(kind, documentTheme) {
18122
18190
  const palette = documentTheme === "dark" ? {
18123
- insertion: "#60a5fa",
18191
+ insertion: "#f87171",
18124
18192
  deletion: "#f87171",
18125
- moveFrom: "#fbbf24",
18126
- moveTo: "#22d3ee",
18193
+ moveFrom: "#86efac",
18194
+ moveTo: "#86efac",
18127
18195
  format: "#c084fc"
18128
18196
  } : {
18129
- insertion: "#2563eb",
18197
+ insertion: "#dc2626",
18130
18198
  deletion: "#dc2626",
18131
- moveFrom: "#d97706",
18132
- moveTo: "#0891b2",
18199
+ moveFrom: "#70ad47",
18200
+ moveTo: "#70ad47",
18133
18201
  format: "#7c3aed"
18134
18202
  };
18135
18203
  switch (kind) {
@@ -18148,6 +18216,9 @@ function trackedChangeAccentColor(kind, documentTheme) {
18148
18216
  return palette.format;
18149
18217
  }
18150
18218
  }
18219
+ function trackedChangeUsesGutterBalloon(change) {
18220
+ return change.kind !== "insertion" && change.kind !== "move-to";
18221
+ }
18151
18222
  function gutterAnnotationSortTuple(location) {
18152
18223
  if (location.kind === "paragraph") {
18153
18224
  return [location.nodeIndex, 0, 0, 0];
@@ -18228,10 +18299,137 @@ function elementRectWithinContainer(element, container) {
18228
18299
  height: elementRect.height / scaleY
18229
18300
  };
18230
18301
  }
18302
+ function findFirstElementWithSpaceSeparatedDataValue(rootElement, attributeName, value) {
18303
+ const candidateElements = [];
18304
+ if (rootElement.hasAttribute(attributeName)) {
18305
+ candidateElements.push(rootElement);
18306
+ }
18307
+ candidateElements.push(
18308
+ ...rootElement.querySelectorAll(
18309
+ `[${attributeName}]`
18310
+ )
18311
+ );
18312
+ for (const candidate of candidateElements) {
18313
+ const rawValue = candidate.getAttribute(attributeName);
18314
+ if (!rawValue) {
18315
+ continue;
18316
+ }
18317
+ if (rawValue.split(/\s+/).includes(value)) {
18318
+ return candidate;
18319
+ }
18320
+ }
18321
+ return void 0;
18322
+ }
18323
+ function findGutterAnnotationScopeElementInPage(pageElement, annotation) {
18324
+ return findTrackedChangeAnchorElementInPage(pageElement, annotation.location);
18325
+ }
18326
+ function findGutterAnnotationDataAnchorInPage(pageElement, annotation, attributeName, value) {
18327
+ const scopedRoot = findGutterAnnotationScopeElementInPage(
18328
+ pageElement,
18329
+ annotation
18330
+ );
18331
+ if (scopedRoot) {
18332
+ const scopedAnchor = findFirstElementWithSpaceSeparatedDataValue(
18333
+ scopedRoot,
18334
+ attributeName,
18335
+ value
18336
+ );
18337
+ if (scopedAnchor) {
18338
+ return scopedAnchor;
18339
+ }
18340
+ }
18341
+ return findFirstElementWithSpaceSeparatedDataValue(
18342
+ pageElement,
18343
+ attributeName,
18344
+ value
18345
+ );
18346
+ }
18347
+ function findGutterAnnotationAnchorElementInPage(pageElement, annotation) {
18348
+ if (annotation.trackedChange) {
18349
+ const trackedAnchor = findGutterAnnotationDataAnchorInPage(
18350
+ pageElement,
18351
+ annotation,
18352
+ "data-docx-tracked-change-id",
18353
+ annotation.trackedChange.id
18354
+ );
18355
+ if (trackedAnchor) {
18356
+ return trackedAnchor;
18357
+ }
18358
+ const inlineAnchorId = annotation.trackedChange.inlineAnchorId;
18359
+ if (inlineAnchorId && inlineAnchorId !== annotation.trackedChange.id) {
18360
+ const inlineTrackedAnchor = findGutterAnnotationDataAnchorInPage(
18361
+ pageElement,
18362
+ annotation,
18363
+ "data-docx-tracked-change-id",
18364
+ inlineAnchorId
18365
+ );
18366
+ if (inlineTrackedAnchor) {
18367
+ return inlineTrackedAnchor;
18368
+ }
18369
+ }
18370
+ }
18371
+ if (annotation.comment) {
18372
+ const commentAnchor = findGutterAnnotationDataAnchorInPage(
18373
+ pageElement,
18374
+ annotation,
18375
+ "data-docx-comment-ids",
18376
+ String(annotation.comment.commentId)
18377
+ );
18378
+ if (commentAnchor) {
18379
+ return commentAnchor;
18380
+ }
18381
+ }
18382
+ return findTrackedChangeAnchorElementInPage(pageElement, annotation.location);
18383
+ }
18231
18384
  function estimateTrackedChangeCardHeight(change) {
18232
18385
  const snippet = normalizeTrackedChangeSnippet(change.text) ?? trackedChangeKindLabel(change.kind);
18233
- const lines = Math.max(1, Math.ceil(snippet.length / 30));
18234
- return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 34 + lines * 14);
18386
+ const lines = Math.min(2, Math.max(1, Math.ceil(snippet.length / 42)));
18387
+ return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 22 + lines * 11);
18388
+ }
18389
+ function assignGutterConnectorLanes(entries) {
18390
+ if (entries.length <= 1) {
18391
+ entries.forEach((entry) => {
18392
+ entry.connectorLane = 0;
18393
+ });
18394
+ return;
18395
+ }
18396
+ const intervalPaddingPx = 3;
18397
+ const laneEndY = Array.from(
18398
+ { length: TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_COUNT },
18399
+ () => Number.NEGATIVE_INFINITY
18400
+ );
18401
+ const routedEntries = entries.map((entry, index) => {
18402
+ const cardCenterY = entry.top + entry.heightPx / 2;
18403
+ return {
18404
+ entry,
18405
+ index,
18406
+ startY: Math.min(entry.anchorY, cardCenterY) - intervalPaddingPx,
18407
+ endY: Math.max(entry.anchorY, cardCenterY) + intervalPaddingPx
18408
+ };
18409
+ }).sort((left, right) => {
18410
+ const startDelta = left.startY - right.startY;
18411
+ if (startDelta !== 0) {
18412
+ return startDelta;
18413
+ }
18414
+ const endDelta = left.endY - right.endY;
18415
+ if (endDelta !== 0) {
18416
+ return endDelta;
18417
+ }
18418
+ return left.index - right.index;
18419
+ });
18420
+ routedEntries.forEach((route) => {
18421
+ let laneIndex = laneEndY.findIndex(
18422
+ (laneEnd) => route.startY > laneEnd + intervalPaddingPx
18423
+ );
18424
+ if (laneIndex < 0) {
18425
+ laneIndex = laneEndY.reduce(
18426
+ (bestLane, laneEnd, index) => laneEnd < laneEndY[bestLane] ? index : bestLane,
18427
+ 0
18428
+ );
18429
+ }
18430
+ route.entry.connectorLane = laneIndex;
18431
+ laneEndY[laneIndex] = Math.max(laneEndY[laneIndex], route.endY);
18432
+ });
18235
18433
  }
18236
18434
  function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsByChangeId, pageWidthPx, pageHeightPx) {
18237
18435
  if (annotations.length === 0) {
@@ -18268,14 +18466,25 @@ function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsB
18268
18466
  Math.max(10, pageHeightPx - 10)
18269
18467
  ),
18270
18468
  top: 0,
18271
- heightPx
18469
+ heightPx,
18470
+ connectorLane: 0
18272
18471
  };
18273
18472
  });
18274
- withAnchors.sort((left, right) => left.anchorY - right.anchorY);
18473
+ withAnchors.sort((left, right) => {
18474
+ const yDelta = left.anchorY - right.anchorY;
18475
+ if (Math.abs(yDelta) > 2) {
18476
+ return yDelta;
18477
+ }
18478
+ const xDelta = left.anchorX - right.anchorX;
18479
+ if (xDelta !== 0) {
18480
+ return xDelta;
18481
+ }
18482
+ return left.annotation.id.localeCompare(right.annotation.id);
18483
+ });
18275
18484
  const minTopPx = 8;
18276
18485
  let cursorTopPx = minTopPx;
18277
18486
  withAnchors.forEach((entry) => {
18278
- const desiredTop = entry.anchorY - Math.round(entry.heightPx / 2);
18487
+ const desiredTop = entry.anchorY - 8;
18279
18488
  entry.top = Math.max(desiredTop, cursorTopPx);
18280
18489
  cursorTopPx = entry.top + entry.heightPx + TRACKED_CHANGE_GUTTER_CARD_GAP_PX;
18281
18490
  });
@@ -18290,6 +18499,7 @@ function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsB
18290
18499
  shiftedCursorTopPx = entry.top + entry.heightPx + TRACKED_CHANGE_GUTTER_CARD_GAP_PX;
18291
18500
  });
18292
18501
  }
18502
+ assignGutterConnectorLanes(withAnchors);
18293
18503
  return withAnchors;
18294
18504
  }
18295
18505
  function sameParagraphLocation(a, b) {
@@ -27458,6 +27668,9 @@ function DocxEditorViewer({
27458
27668
  };
27459
27669
  if (trackedChangesEnabled) {
27460
27670
  editor.trackedChanges.forEach((change) => {
27671
+ if (!trackedChangeUsesGutterBalloon(change)) {
27672
+ return;
27673
+ }
27461
27674
  placeAnnotation({
27462
27675
  id: change.id,
27463
27676
  location: change.location,
@@ -27508,45 +27721,45 @@ function DocxEditorViewer({
27508
27721
  );
27509
27722
  return;
27510
27723
  }
27511
- const nextAnchorMaps = trackedChangesByPage.map((annotations, pageIndex) => {
27512
- const pageElement = pageElementsRef.current.get(pageIndex);
27513
- const anchorsByChangeId = /* @__PURE__ */ new Map();
27514
- if (!pageElement || annotations.length === 0) {
27724
+ const nextAnchorMaps = trackedChangesByPage.map(
27725
+ (annotations, pageIndex) => {
27726
+ const pageElement = pageElementsRef.current.get(pageIndex);
27727
+ const anchorsByChangeId = /* @__PURE__ */ new Map();
27728
+ if (!pageElement || annotations.length === 0) {
27729
+ return anchorsByChangeId;
27730
+ }
27731
+ const pageHeightPx = Math.max(1, pageElement.offsetHeight);
27732
+ const pageWidthPx = Math.max(1, pageElement.offsetWidth);
27733
+ annotations.forEach((annotation) => {
27734
+ const anchorElement = findGutterAnnotationAnchorElementInPage(
27735
+ pageElement,
27736
+ annotation
27737
+ );
27738
+ if (!anchorElement) {
27739
+ return;
27740
+ }
27741
+ const anchorRect = elementRectWithinContainer(
27742
+ anchorElement,
27743
+ pageElement
27744
+ );
27745
+ if (!anchorRect) {
27746
+ return;
27747
+ }
27748
+ const anchorY = clampNumber(
27749
+ Math.round(anchorRect.top + anchorRect.height / 2),
27750
+ 10,
27751
+ Math.max(10, pageHeightPx - 10)
27752
+ );
27753
+ const anchorX = clampNumber(
27754
+ Math.round(anchorRect.right),
27755
+ 10,
27756
+ Math.max(10, pageWidthPx - 10)
27757
+ );
27758
+ anchorsByChangeId.set(annotation.id, { x: anchorX, y: anchorY });
27759
+ });
27515
27760
  return anchorsByChangeId;
27516
27761
  }
27517
- const pageHeightPx = Math.max(1, pageElement.offsetHeight);
27518
- const pageWidthPx = Math.max(1, pageElement.offsetWidth);
27519
- annotations.forEach((annotation) => {
27520
- const anchorElement = findTrackedChangeAnchorElementInPage(
27521
- pageElement,
27522
- annotation.location
27523
- );
27524
- if (!anchorElement) {
27525
- return;
27526
- }
27527
- const anchorRect = elementRectWithinContainer(
27528
- anchorElement,
27529
- pageElement
27530
- );
27531
- if (!anchorRect) {
27532
- return;
27533
- }
27534
- const anchorY = clampNumber(
27535
- Math.round(anchorRect.top + anchorRect.height / 2),
27536
- 10,
27537
- Math.max(10, pageHeightPx - 10)
27538
- );
27539
- const anchorX = clampNumber(
27540
- Math.round(
27541
- anchorRect.left + Math.min(24, Math.max(8, anchorRect.width * 0.2))
27542
- ),
27543
- 10,
27544
- Math.max(10, pageWidthPx - 10)
27545
- );
27546
- anchorsByChangeId.set(annotation.id, { x: anchorX, y: anchorY });
27547
- });
27548
- return anchorsByChangeId;
27549
- });
27762
+ );
27550
27763
  setTrackedChangeAnchorByPage(nextAnchorMaps);
27551
27764
  }, [
27552
27765
  trackedChangesByPage,
@@ -41397,6 +41610,7 @@ ${currentText.slice(end)}`;
41397
41610
  });
41398
41611
  const headerFooterBodyDimmed = pageHeaderFooterEditActive;
41399
41612
  const documentPageBackgroundColor = editor.model.metadata.documentBackgroundColor;
41613
+ const resolvedPageSurfaceBackgroundColor = pageBackgroundColor ?? documentPageBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor;
41400
41614
  const pageBorders = parseSectionPageBorders(
41401
41615
  pageInfo?.section.sectionPropertiesXml ?? editor.model.metadata.sectionPropertiesXml
41402
41616
  );
@@ -41419,7 +41633,7 @@ ${currentText.slice(end)}`;
41419
41633
  width: pageLayout.pageWidthPx,
41420
41634
  height: pageLayout.pageHeightPx,
41421
41635
  minHeight: pageLayout.pageHeightPx,
41422
- backgroundColor: pageBackgroundColor ?? documentPageBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor,
41636
+ backgroundColor: resolvedPageSurfaceBackgroundColor,
41423
41637
  position: "relative",
41424
41638
  ...pageMarginPaddingStyle(pageLayout.marginsPx)
41425
41639
  };
@@ -42521,6 +42735,7 @@ ${currentText.slice(end)}`;
42521
42735
  top: 0,
42522
42736
  width: TRACKED_CHANGE_GUTTER_WIDTH_PX,
42523
42737
  height: pageLayout.pageHeightPx,
42738
+ backgroundColor: resolvedPageSurfaceBackgroundColor,
42524
42739
  pointerEvents: "none",
42525
42740
  overflow: "visible"
42526
42741
  },
@@ -42551,14 +42766,14 @@ ${currentText.slice(end)}`;
42551
42766
  overflow: "visible"
42552
42767
  },
42553
42768
  children: pageTrackedChanges.map((entry) => {
42554
- const accentColor = entry.annotation.trackedChange ? trackedChangeAccentColor(
42555
- entry.annotation.trackedChange.kind,
42769
+ const trackedChange = entry.annotation.trackedChange;
42770
+ const comment = entry.annotation.comment;
42771
+ const accentColor = trackedChange ? trackedChangeAccentColor(
42772
+ trackedChange.kind,
42556
42773
  editor.documentTheme
42557
- ) : commentAccentColor(editor.documentTheme);
42558
- const cardCenterY = clampNumber(
42559
- Math.round(entry.top + entry.heightPx / 2),
42560
- 8,
42561
- Math.max(8, pageLayout.pageHeightPx - 8)
42774
+ ) : commentAccentColor(
42775
+ editor.documentTheme,
42776
+ comment?.commentId
42562
42777
  );
42563
42778
  const anchorY = clampNumber(
42564
42779
  Math.round(entry.anchorY),
@@ -42570,48 +42785,58 @@ ${currentText.slice(end)}`;
42570
42785
  8,
42571
42786
  Math.max(8, pageLayout.pageWidthPx - 8)
42572
42787
  );
42573
- const cardLeadX = pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_CARD_LEFT_PX - 6;
42574
- const bendX = clampNumber(
42575
- Math.round((anchorX + cardLeadX) / 2),
42576
- anchorX + 8,
42577
- Math.max(anchorX + 8, cardLeadX - 8)
42788
+ const cardAttachX = pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_CARD_LEFT_PX;
42789
+ const maxConnectorLaneOffset = Math.max(
42790
+ TRACKED_CHANGE_GUTTER_BEND_OFFSET_PX,
42791
+ TRACKED_CHANGE_GUTTER_CARD_LEFT_PX - 6
42792
+ );
42793
+ const connectorLaneOffset = Math.min(
42794
+ TRACKED_CHANGE_GUTTER_BEND_OFFSET_PX + Math.max(0, entry.connectorLane) * TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_GAP_PX,
42795
+ maxConnectorLaneOffset
42796
+ );
42797
+ const gutterBendX = pageLayout.pageWidthPx + connectorLaneOffset;
42798
+ const cardCenterY = clampNumber(
42799
+ Math.round(entry.top + entry.heightPx / 2),
42800
+ 8,
42801
+ Math.max(8, pageLayout.pageHeightPx - 8)
42802
+ );
42803
+ const connectorPath = Math.abs(cardCenterY - anchorY) <= 2 ? `M ${anchorX} ${anchorY} H ${cardAttachX}` : `M ${anchorX} ${anchorY} H ${gutterBendX} V ${cardCenterY} H ${cardAttachX}`;
42804
+ const revisionBarX = clampNumber(
42805
+ Math.round(pageLayout.marginsPx.left - 20),
42806
+ 8,
42807
+ Math.max(8, pageLayout.pageWidthPx - 8)
42578
42808
  );
42579
42809
  return /* @__PURE__ */ jsxs(
42580
42810
  "g",
42581
42811
  {
42582
42812
  children: [
42813
+ trackedChange ? /* @__PURE__ */ jsx(
42814
+ "line",
42815
+ {
42816
+ x1: revisionBarX,
42817
+ y1: Math.max(8, anchorY - 16),
42818
+ x2: revisionBarX,
42819
+ y2: Math.min(
42820
+ pageLayout.pageHeightPx - 8,
42821
+ anchorY + 16
42822
+ ),
42823
+ stroke: editor.documentTheme === "dark" ? "#94a3b8" : "#9ca3af",
42824
+ strokeWidth: 1.25,
42825
+ strokeLinecap: "square"
42826
+ }
42827
+ ) : null,
42583
42828
  /* @__PURE__ */ jsx(
42584
42829
  "path",
42585
42830
  {
42586
- d: `M ${anchorX} ${anchorY} L ${bendX} ${anchorY} L ${cardLeadX} ${cardCenterY}`,
42831
+ d: connectorPath,
42587
42832
  stroke: accentColor,
42588
- strokeWidth: 1.75,
42589
- strokeOpacity: 1,
42590
- strokeDasharray: "5 4",
42833
+ strokeWidth: 1.15,
42834
+ strokeOpacity: 0.78,
42835
+ strokeDasharray: "2 3",
42591
42836
  strokeLinejoin: "round",
42592
42837
  strokeLinecap: "round",
42593
42838
  fill: "none"
42594
42839
  }
42595
- ),
42596
- /* @__PURE__ */ jsx(
42597
- "circle",
42598
- {
42599
- cx: anchorX,
42600
- cy: anchorY,
42601
- r: 2.2,
42602
- fill: accentColor,
42603
- stroke: editor.documentTheme === "dark" ? "#020617" : "#ffffff",
42604
- strokeWidth: 1
42605
- }
42606
- ),
42607
- /* @__PURE__ */ jsx(
42608
- "circle",
42609
- {
42610
- cx: cardLeadX,
42611
- cy: cardCenterY,
42612
- r: 1.8,
42613
- fill: accentColor
42614
- }
42615
42840
  )
42616
42841
  ]
42617
42842
  },
@@ -42642,7 +42867,10 @@ ${currentText.slice(end)}`;
42642
42867
  const accentColor = trackedChange ? trackedChangeAccentColor(
42643
42868
  trackedChange.kind,
42644
42869
  editor.documentTheme
42645
- ) : commentAccentColor(editor.documentTheme);
42870
+ ) : commentAccentColor(
42871
+ editor.documentTheme,
42872
+ comment?.commentId
42873
+ );
42646
42874
  const formattedDate = formatTrackedChangeDate(
42647
42875
  trackedChange?.date ?? comment?.date
42648
42876
  );
@@ -42669,15 +42897,15 @@ ${currentText.slice(end)}`;
42669
42897
  {
42670
42898
  style: {
42671
42899
  ...cardStyle,
42672
- padding: "6px 8px",
42900
+ padding: "4px 6px",
42673
42901
  boxSizing: "border-box",
42674
- borderLeft: `2px solid ${accentColor}`,
42675
- borderTop: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.28)" : "rgba(15, 23, 42, 0.12)"}`,
42676
- borderRight: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.28)" : "rgba(15, 23, 42, 0.12)"}`,
42677
- borderBottom: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.28)" : "rgba(15, 23, 42, 0.12)"}`,
42678
- backgroundColor: editor.documentTheme === "dark" ? "rgba(2, 6, 23, 0.96)" : "rgba(255, 255, 255, 0.96)",
42902
+ borderLeft: `1.5px solid ${accentColor}`,
42903
+ borderTop: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.18)" : "rgba(15, 23, 42, 0.08)"}`,
42904
+ borderRight: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.18)" : "rgba(15, 23, 42, 0.08)"}`,
42905
+ borderBottom: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.18)" : "rgba(15, 23, 42, 0.08)"}`,
42906
+ backgroundColor: editor.documentTheme === "dark" ? "rgba(15, 23, 42, 0.92)" : "rgba(255, 255, 255, 0.72)",
42679
42907
  color: editor.documentTheme === "dark" ? "#f3f4f6" : "#111827",
42680
- boxShadow: editor.documentTheme === "dark" ? "0 2px 6px rgba(2, 6, 23, 0.55)" : "0 1px 2px rgba(15, 23, 42, 0.14)"
42908
+ boxShadow: editor.documentTheme === "dark" ? "0 1px 2px rgba(2, 6, 23, 0.45)" : "0 1px 1px rgba(15, 23, 42, 0.08)"
42681
42909
  },
42682
42910
  children: [
42683
42911
  /* @__PURE__ */ jsxs(
@@ -42695,9 +42923,9 @@ ${currentText.slice(end)}`;
42695
42923
  {
42696
42924
  style: {
42697
42925
  margin: 0,
42698
- fontSize: 12,
42926
+ fontSize: 10,
42699
42927
  fontWeight: 700,
42700
- lineHeight: 1.25
42928
+ lineHeight: 1.2
42701
42929
  },
42702
42930
  children: (trackedChange?.author ?? comment?.author)?.trim() || "Unknown author"
42703
42931
  }
@@ -42707,8 +42935,8 @@ ${currentText.slice(end)}`;
42707
42935
  {
42708
42936
  style: {
42709
42937
  margin: 0,
42710
- fontSize: 11,
42711
- lineHeight: 1.2,
42938
+ fontSize: 9,
42939
+ lineHeight: 1.15,
42712
42940
  color: editor.documentTheme === "dark" ? "#94a3b8" : "#6b7280",
42713
42941
  whiteSpace: "nowrap"
42714
42942
  },
@@ -42723,8 +42951,8 @@ ${currentText.slice(end)}`;
42723
42951
  {
42724
42952
  style: {
42725
42953
  margin: "2px 0 0",
42726
- fontSize: 11,
42727
- lineHeight: 1.3,
42954
+ fontSize: 9,
42955
+ lineHeight: 1.25,
42728
42956
  fontStyle: "italic",
42729
42957
  color: editor.documentTheme === "dark" ? "#94a3b8" : "#6b7280"
42730
42958
  },
@@ -42740,8 +42968,8 @@ ${currentText.slice(end)}`;
42740
42968
  {
42741
42969
  style: {
42742
42970
  margin: "2px 0 0",
42743
- fontSize: 12,
42744
- lineHeight: 1.35
42971
+ fontSize: 10,
42972
+ lineHeight: 1.25
42745
42973
  },
42746
42974
  children: [
42747
42975
  /* @__PURE__ */ jsxs("strong", { children: [
@@ -42778,6 +43006,10 @@ ${currentText.slice(end)}`;
42778
43006
  "div",
42779
43007
  {
42780
43008
  "data-docx-gutter-annotation": trackedChange ? "tracked-change" : "comment",
43009
+ "data-docx-gutter-annotation-id": entry.annotation.id,
43010
+ "data-docx-gutter-anchor-x": Math.round(entry.anchorX),
43011
+ "data-docx-gutter-anchor-y": Math.round(entry.anchorY),
43012
+ "data-docx-gutter-connector-lane": entry.connectorLane,
42781
43013
  ref: (element) => {
42782
43014
  const elementKey = `${pageIndex}:${entry.annotation.id}`;
42783
43015
  if (element) {