@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.cjs CHANGED
@@ -5834,10 +5834,13 @@ var BASE_DOC_STYLE = {
5834
5834
  transition: "box-shadow 0.2s ease"
5835
5835
  };
5836
5836
  var TRACKED_CHANGE_GUTTER_WIDTH_PX = 300;
5837
- var TRACKED_CHANGE_GUTTER_CARD_LEFT_PX = 28;
5838
- var TRACKED_CHANGE_GUTTER_CARD_RIGHT_PX = 10;
5839
- var TRACKED_CHANGE_GUTTER_CARD_GAP_PX = 8;
5840
- var TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX = 52;
5837
+ var TRACKED_CHANGE_GUTTER_CARD_LEFT_PX = 48;
5838
+ var TRACKED_CHANGE_GUTTER_CARD_RIGHT_PX = 12;
5839
+ var TRACKED_CHANGE_GUTTER_CARD_GAP_PX = 4;
5840
+ var TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX = 30;
5841
+ var TRACKED_CHANGE_GUTTER_BEND_OFFSET_PX = 8;
5842
+ var TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_GAP_PX = 7;
5843
+ var TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_COUNT = 5;
5841
5844
  var INITIAL_PAGINATION_STABILITY_IDLE_MS = 240;
5842
5845
  function scheduleDomWrite(callback) {
5843
5846
  if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
@@ -14250,9 +14253,10 @@ function trackedInlineStyle(baseStyle, change) {
14250
14253
  return baseStyle;
14251
14254
  }
14252
14255
  if (change.kind === "insertion" || change.kind === "move-to") {
14256
+ const accentColor = change.kind === "move-to" ? "#70ad47" : "#dc2626";
14253
14257
  return {
14254
14258
  ...baseStyle,
14255
- color: "#2563eb",
14259
+ color: accentColor,
14256
14260
  textDecoration: mergeTextDecorations(
14257
14261
  baseStyle.textDecoration,
14258
14262
  "underline"
@@ -15877,11 +15881,22 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15877
15881
  if (!commentIds || commentIds.length === 0) {
15878
15882
  return void 0;
15879
15883
  }
15880
- const accent = commentAccentColor(documentTheme);
15881
- return {
15882
- backgroundColor: documentTheme === "dark" ? "rgba(251, 191, 36, 0.24)" : "rgba(251, 191, 36, 0.3)",
15883
- borderBottom: `2px solid ${accent}`
15884
- };
15884
+ return commentHighlightStyle(documentTheme, commentIds[0]);
15885
+ };
15886
+ const currentAnnotationAttributes = (trackedInlineChange) => {
15887
+ const attributes = {};
15888
+ if (trackedInlineChange) {
15889
+ attributes["data-docx-tracked-change"] = trackedInlineChange.kind;
15890
+ attributes["data-docx-tracked-change-id"] = trackedInlineChange.id;
15891
+ }
15892
+ const commentIds = commentMarkup?.commentIdsByVisibleChildIndex[trackedVisibleChildCursor];
15893
+ if (commentIds && commentIds.length > 0) {
15894
+ attributes["data-docx-comment-ids"] = commentIds.join(" ");
15895
+ if (commentIds.length === 1) {
15896
+ attributes["data-docx-comment-id"] = String(commentIds[0]);
15897
+ }
15898
+ }
15899
+ return attributes;
15885
15900
  };
15886
15901
  const consumeTrackedVisibleChild = (child) => {
15887
15902
  if (!trackedMarkup && !commentMarkup) {
@@ -15915,11 +15930,11 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15915
15930
  fallbackTabWidthPx,
15916
15931
  checkboxChoiceRow
15917
15932
  );
15918
- const appendPlainTextWithSoftBreakControl = (target, keySeed, text, style, measureStyle) => {
15933
+ const appendPlainTextWithSoftBreakControl = (target, keySeed, text, style, measureStyle, spanAttributes) => {
15919
15934
  const shouldControlSoftBreakStretch = paragraph.style?.align === "justify" && text.includes("\n");
15920
15935
  if (!shouldControlSoftBreakStretch) {
15921
15936
  target.push(
15922
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style, children: text }, keySeed)
15937
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...spanAttributes, style, children: text }, keySeed)
15923
15938
  );
15924
15939
  trackTextAdvance(text, measureStyle);
15925
15940
  return;
@@ -15935,6 +15950,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
15935
15950
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
15936
15951
  "span",
15937
15952
  {
15953
+ ...spanAttributes,
15938
15954
  style: isLastSegment ? {
15939
15955
  ...style,
15940
15956
  display: "inline-block",
@@ -16085,6 +16101,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16085
16101
  " "
16086
16102
  );
16087
16103
  const text = textOverride ?? textValue;
16104
+ const annotationAttributes2 = currentAnnotationAttributes(trackedInlineChange);
16088
16105
  if (child.link) {
16089
16106
  const linkHref = child.link;
16090
16107
  const isInternalLink = linkHref.startsWith("#");
@@ -16092,6 +16109,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16092
16109
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
16093
16110
  "a",
16094
16111
  {
16112
+ ...annotationAttributes2,
16095
16113
  href: linkHref,
16096
16114
  target: isInternalLink ? void 0 : "_blank",
16097
16115
  rel: isInternalLink ? void 0 : "noreferrer noopener",
@@ -16128,12 +16146,20 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16128
16146
  };
16129
16147
  if (text === " " && !useTabLeaderLayout && !useAnchoredTabLayout) {
16130
16148
  target.push(
16131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: tabTextStyle(child.style, trackedStyle), children: "\xA0" }, key)
16149
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
16150
+ "span",
16151
+ {
16152
+ ...annotationAttributes2,
16153
+ style: tabTextStyle(child.style, trackedStyle),
16154
+ children: "\xA0"
16155
+ },
16156
+ key
16157
+ )
16132
16158
  );
16133
16159
  return;
16134
16160
  }
16135
16161
  target.push(
16136
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: trackedStyle, children: text }, key)
16162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...annotationAttributes2, style: trackedStyle, children: text }, key)
16137
16163
  );
16138
16164
  trackTextAdvance(text, child.style);
16139
16165
  return;
@@ -16202,7 +16228,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16202
16228
  const sectionImageCursor = sectionImageLocation && !sectionImageInteraction?.isReadOnly && !behavesAsDecorativeBehindTextBackground && (isWrappedFloatingImage || isAbsoluteFloatingImage) ? "move" : void 0;
16203
16229
  const isCenteredStandaloneInlineImage = !isWrappedFloatingImage && !isAbsoluteFloatingImage && paragraph.style?.align === "center" && paragraph.children.length === 1 && paragraph.children[0]?.type === "image";
16204
16230
  const trackedImageStyle = trackedInlineChange?.kind === "insertion" || trackedInlineChange?.kind === "move-to" ? {
16205
- outline: "2px solid rgba(37, 99, 235, 0.35)",
16231
+ outline: trackedInlineChange.kind === "move-to" ? "2px solid rgba(112, 173, 71, 0.35)" : "2px solid rgba(220, 38, 38, 0.3)",
16206
16232
  outlineOffset: 1
16207
16233
  } : void 0;
16208
16234
  const renderableImageSrc = syntheticTextBoxSvg(
@@ -16388,6 +16414,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16388
16414
  ),
16389
16415
  ...currentCommentHighlightStyle()
16390
16416
  };
16417
+ const annotationAttributes = currentAnnotationAttributes(trackedInlineChange);
16391
16418
  const noteLabel = noteMarkerLabel(
16392
16419
  child.noteReference,
16393
16420
  safeNoteMarkerIndexes.footnote,
@@ -16398,6 +16425,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16398
16425
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
16399
16426
  "span",
16400
16427
  {
16428
+ ...annotationAttributes,
16401
16429
  style: {
16402
16430
  ...textStyle,
16403
16431
  verticalAlign: "super",
@@ -16413,7 +16441,15 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16413
16441
  }
16414
16442
  if ((textOverride ?? child.text) === " " && !useTabLeaderLayout && !useAnchoredTabLayout) {
16415
16443
  target.push(
16416
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: tabTextStyle(child.style, textStyle), children: "\xA0" }, key)
16444
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
16445
+ "span",
16446
+ {
16447
+ ...annotationAttributes,
16448
+ style: tabTextStyle(child.style, textStyle),
16449
+ children: "\xA0"
16450
+ },
16451
+ key
16452
+ )
16417
16453
  );
16418
16454
  return;
16419
16455
  }
@@ -16424,6 +16460,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16424
16460
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
16425
16461
  "a",
16426
16462
  {
16463
+ ...annotationAttributes,
16427
16464
  href: linkHref,
16428
16465
  target: isInternalLink ? void 0 : "_blank",
16429
16466
  rel: isInternalLink ? void 0 : "noreferrer noopener",
@@ -16456,7 +16493,8 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
16456
16493
  key,
16457
16494
  textOverride ?? child.text,
16458
16495
  textStyle,
16459
- child.style
16496
+ child.style,
16497
+ annotationAttributes
16460
16498
  );
16461
16499
  };
16462
16500
  const anchoredTabZoneStyle = {
@@ -19167,6 +19205,7 @@ function collectTrackedChangesFromModel(model) {
19167
19205
  trackedMarkup.changes.forEach((change, changeIndex) => {
19168
19206
  trackedChanges.push({
19169
19207
  id: `${paragraphLocationKey(location)}:${change.id}:${changeIndex}`,
19208
+ inlineAnchorId: change.id,
19170
19209
  kind: change.kind,
19171
19210
  author: change.author,
19172
19211
  date: change.date,
@@ -19345,13 +19384,42 @@ function collectCommentsFromModel(model) {
19345
19384
  });
19346
19385
  return comments;
19347
19386
  }
19348
- function commentAccentColor(documentTheme) {
19349
- return documentTheme === "dark" ? "#fbbf24" : "#d97706";
19387
+ function hexColorWithAlpha(color, alpha) {
19388
+ const normalized = color.trim().replace(/^#/, "");
19389
+ if (!/^[\da-f]{6}$/i.test(normalized)) {
19390
+ return color;
19391
+ }
19392
+ const red = Number.parseInt(normalized.slice(0, 2), 16);
19393
+ const green = Number.parseInt(normalized.slice(2, 4), 16);
19394
+ const blue = Number.parseInt(normalized.slice(4, 6), 16);
19395
+ return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
19396
+ }
19397
+ function commentAccentColor(documentTheme, commentId) {
19398
+ const lightPalette = ["#5b9bd5", "#d65f5f", "#8f6ac8", "#70ad47", "#d9872b"];
19399
+ const darkPalette = ["#7dd3fc", "#fca5a5", "#c4b5fd", "#86efac", "#fdba74"];
19400
+ if (Number.isFinite(commentId)) {
19401
+ const palette = documentTheme === "dark" ? darkPalette : lightPalette;
19402
+ return palette[Math.abs(Math.round(commentId)) % palette.length];
19403
+ }
19404
+ return documentTheme === "dark" ? darkPalette[0] : lightPalette[0];
19405
+ }
19406
+ function commentHighlightStyle(documentTheme, commentId) {
19407
+ const accent = commentAccentColor(documentTheme, commentId);
19408
+ return {
19409
+ backgroundColor: hexColorWithAlpha(
19410
+ accent,
19411
+ documentTheme === "dark" ? 0.3 : 0.22
19412
+ ),
19413
+ boxShadow: `inset 0 -1px 0 ${hexColorWithAlpha(
19414
+ accent,
19415
+ documentTheme === "dark" ? 0.7 : 0.48
19416
+ )}`
19417
+ };
19350
19418
  }
19351
19419
  function estimateCommentCardHeight(comment) {
19352
19420
  const snippet = comment.text || "Comment";
19353
- const lines = Math.max(1, Math.ceil(snippet.length / 30));
19354
- return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 34 + lines * 14);
19421
+ const lines = Math.min(2, Math.max(1, Math.ceil(snippet.length / 42)));
19422
+ return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 24 + lines * 11);
19355
19423
  }
19356
19424
  function trackedChangeKindLabel(kind) {
19357
19425
  switch (kind) {
@@ -19373,16 +19441,16 @@ function trackedChangeKindLabel(kind) {
19373
19441
  }
19374
19442
  function trackedChangeAccentColor(kind, documentTheme) {
19375
19443
  const palette = documentTheme === "dark" ? {
19376
- insertion: "#60a5fa",
19444
+ insertion: "#f87171",
19377
19445
  deletion: "#f87171",
19378
- moveFrom: "#fbbf24",
19379
- moveTo: "#22d3ee",
19446
+ moveFrom: "#86efac",
19447
+ moveTo: "#86efac",
19380
19448
  format: "#c084fc"
19381
19449
  } : {
19382
- insertion: "#2563eb",
19450
+ insertion: "#dc2626",
19383
19451
  deletion: "#dc2626",
19384
- moveFrom: "#d97706",
19385
- moveTo: "#0891b2",
19452
+ moveFrom: "#70ad47",
19453
+ moveTo: "#70ad47",
19386
19454
  format: "#7c3aed"
19387
19455
  };
19388
19456
  switch (kind) {
@@ -19401,6 +19469,9 @@ function trackedChangeAccentColor(kind, documentTheme) {
19401
19469
  return palette.format;
19402
19470
  }
19403
19471
  }
19472
+ function trackedChangeUsesGutterBalloon(change) {
19473
+ return change.kind !== "insertion" && change.kind !== "move-to";
19474
+ }
19404
19475
  function gutterAnnotationSortTuple(location) {
19405
19476
  if (location.kind === "paragraph") {
19406
19477
  return [location.nodeIndex, 0, 0, 0];
@@ -19481,10 +19552,137 @@ function elementRectWithinContainer(element, container) {
19481
19552
  height: elementRect.height / scaleY
19482
19553
  };
19483
19554
  }
19555
+ function findFirstElementWithSpaceSeparatedDataValue(rootElement, attributeName, value) {
19556
+ const candidateElements = [];
19557
+ if (rootElement.hasAttribute(attributeName)) {
19558
+ candidateElements.push(rootElement);
19559
+ }
19560
+ candidateElements.push(
19561
+ ...rootElement.querySelectorAll(
19562
+ `[${attributeName}]`
19563
+ )
19564
+ );
19565
+ for (const candidate of candidateElements) {
19566
+ const rawValue = candidate.getAttribute(attributeName);
19567
+ if (!rawValue) {
19568
+ continue;
19569
+ }
19570
+ if (rawValue.split(/\s+/).includes(value)) {
19571
+ return candidate;
19572
+ }
19573
+ }
19574
+ return void 0;
19575
+ }
19576
+ function findGutterAnnotationScopeElementInPage(pageElement, annotation) {
19577
+ return findTrackedChangeAnchorElementInPage(pageElement, annotation.location);
19578
+ }
19579
+ function findGutterAnnotationDataAnchorInPage(pageElement, annotation, attributeName, value) {
19580
+ const scopedRoot = findGutterAnnotationScopeElementInPage(
19581
+ pageElement,
19582
+ annotation
19583
+ );
19584
+ if (scopedRoot) {
19585
+ const scopedAnchor = findFirstElementWithSpaceSeparatedDataValue(
19586
+ scopedRoot,
19587
+ attributeName,
19588
+ value
19589
+ );
19590
+ if (scopedAnchor) {
19591
+ return scopedAnchor;
19592
+ }
19593
+ }
19594
+ return findFirstElementWithSpaceSeparatedDataValue(
19595
+ pageElement,
19596
+ attributeName,
19597
+ value
19598
+ );
19599
+ }
19600
+ function findGutterAnnotationAnchorElementInPage(pageElement, annotation) {
19601
+ if (annotation.trackedChange) {
19602
+ const trackedAnchor = findGutterAnnotationDataAnchorInPage(
19603
+ pageElement,
19604
+ annotation,
19605
+ "data-docx-tracked-change-id",
19606
+ annotation.trackedChange.id
19607
+ );
19608
+ if (trackedAnchor) {
19609
+ return trackedAnchor;
19610
+ }
19611
+ const inlineAnchorId = annotation.trackedChange.inlineAnchorId;
19612
+ if (inlineAnchorId && inlineAnchorId !== annotation.trackedChange.id) {
19613
+ const inlineTrackedAnchor = findGutterAnnotationDataAnchorInPage(
19614
+ pageElement,
19615
+ annotation,
19616
+ "data-docx-tracked-change-id",
19617
+ inlineAnchorId
19618
+ );
19619
+ if (inlineTrackedAnchor) {
19620
+ return inlineTrackedAnchor;
19621
+ }
19622
+ }
19623
+ }
19624
+ if (annotation.comment) {
19625
+ const commentAnchor = findGutterAnnotationDataAnchorInPage(
19626
+ pageElement,
19627
+ annotation,
19628
+ "data-docx-comment-ids",
19629
+ String(annotation.comment.commentId)
19630
+ );
19631
+ if (commentAnchor) {
19632
+ return commentAnchor;
19633
+ }
19634
+ }
19635
+ return findTrackedChangeAnchorElementInPage(pageElement, annotation.location);
19636
+ }
19484
19637
  function estimateTrackedChangeCardHeight(change) {
19485
19638
  const snippet = normalizeTrackedChangeSnippet(change.text) ?? trackedChangeKindLabel(change.kind);
19486
- const lines = Math.max(1, Math.ceil(snippet.length / 30));
19487
- return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 34 + lines * 14);
19639
+ const lines = Math.min(2, Math.max(1, Math.ceil(snippet.length / 42)));
19640
+ return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 22 + lines * 11);
19641
+ }
19642
+ function assignGutterConnectorLanes(entries) {
19643
+ if (entries.length <= 1) {
19644
+ entries.forEach((entry) => {
19645
+ entry.connectorLane = 0;
19646
+ });
19647
+ return;
19648
+ }
19649
+ const intervalPaddingPx = 3;
19650
+ const laneEndY = Array.from(
19651
+ { length: TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_COUNT },
19652
+ () => Number.NEGATIVE_INFINITY
19653
+ );
19654
+ const routedEntries = entries.map((entry, index) => {
19655
+ const cardCenterY = entry.top + entry.heightPx / 2;
19656
+ return {
19657
+ entry,
19658
+ index,
19659
+ startY: Math.min(entry.anchorY, cardCenterY) - intervalPaddingPx,
19660
+ endY: Math.max(entry.anchorY, cardCenterY) + intervalPaddingPx
19661
+ };
19662
+ }).sort((left, right) => {
19663
+ const startDelta = left.startY - right.startY;
19664
+ if (startDelta !== 0) {
19665
+ return startDelta;
19666
+ }
19667
+ const endDelta = left.endY - right.endY;
19668
+ if (endDelta !== 0) {
19669
+ return endDelta;
19670
+ }
19671
+ return left.index - right.index;
19672
+ });
19673
+ routedEntries.forEach((route) => {
19674
+ let laneIndex = laneEndY.findIndex(
19675
+ (laneEnd) => route.startY > laneEnd + intervalPaddingPx
19676
+ );
19677
+ if (laneIndex < 0) {
19678
+ laneIndex = laneEndY.reduce(
19679
+ (bestLane, laneEnd, index) => laneEnd < laneEndY[bestLane] ? index : bestLane,
19680
+ 0
19681
+ );
19682
+ }
19683
+ route.entry.connectorLane = laneIndex;
19684
+ laneEndY[laneIndex] = Math.max(laneEndY[laneIndex], route.endY);
19685
+ });
19488
19686
  }
19489
19687
  function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsByChangeId, pageWidthPx, pageHeightPx) {
19490
19688
  if (annotations.length === 0) {
@@ -19521,14 +19719,25 @@ function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsB
19521
19719
  Math.max(10, pageHeightPx - 10)
19522
19720
  ),
19523
19721
  top: 0,
19524
- heightPx
19722
+ heightPx,
19723
+ connectorLane: 0
19525
19724
  };
19526
19725
  });
19527
- withAnchors.sort((left, right) => left.anchorY - right.anchorY);
19726
+ withAnchors.sort((left, right) => {
19727
+ const yDelta = left.anchorY - right.anchorY;
19728
+ if (Math.abs(yDelta) > 2) {
19729
+ return yDelta;
19730
+ }
19731
+ const xDelta = left.anchorX - right.anchorX;
19732
+ if (xDelta !== 0) {
19733
+ return xDelta;
19734
+ }
19735
+ return left.annotation.id.localeCompare(right.annotation.id);
19736
+ });
19528
19737
  const minTopPx = 8;
19529
19738
  let cursorTopPx = minTopPx;
19530
19739
  withAnchors.forEach((entry) => {
19531
- const desiredTop = entry.anchorY - Math.round(entry.heightPx / 2);
19740
+ const desiredTop = entry.anchorY - 8;
19532
19741
  entry.top = Math.max(desiredTop, cursorTopPx);
19533
19742
  cursorTopPx = entry.top + entry.heightPx + TRACKED_CHANGE_GUTTER_CARD_GAP_PX;
19534
19743
  });
@@ -19543,6 +19752,7 @@ function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsB
19543
19752
  shiftedCursorTopPx = entry.top + entry.heightPx + TRACKED_CHANGE_GUTTER_CARD_GAP_PX;
19544
19753
  });
19545
19754
  }
19755
+ assignGutterConnectorLanes(withAnchors);
19546
19756
  return withAnchors;
19547
19757
  }
19548
19758
  function sameParagraphLocation(a, b) {
@@ -28711,6 +28921,9 @@ function DocxEditorViewer({
28711
28921
  };
28712
28922
  if (trackedChangesEnabled) {
28713
28923
  editor.trackedChanges.forEach((change) => {
28924
+ if (!trackedChangeUsesGutterBalloon(change)) {
28925
+ return;
28926
+ }
28714
28927
  placeAnnotation({
28715
28928
  id: change.id,
28716
28929
  location: change.location,
@@ -28761,45 +28974,45 @@ function DocxEditorViewer({
28761
28974
  );
28762
28975
  return;
28763
28976
  }
28764
- const nextAnchorMaps = trackedChangesByPage.map((annotations, pageIndex) => {
28765
- const pageElement = pageElementsRef.current.get(pageIndex);
28766
- const anchorsByChangeId = /* @__PURE__ */ new Map();
28767
- if (!pageElement || annotations.length === 0) {
28977
+ const nextAnchorMaps = trackedChangesByPage.map(
28978
+ (annotations, pageIndex) => {
28979
+ const pageElement = pageElementsRef.current.get(pageIndex);
28980
+ const anchorsByChangeId = /* @__PURE__ */ new Map();
28981
+ if (!pageElement || annotations.length === 0) {
28982
+ return anchorsByChangeId;
28983
+ }
28984
+ const pageHeightPx = Math.max(1, pageElement.offsetHeight);
28985
+ const pageWidthPx = Math.max(1, pageElement.offsetWidth);
28986
+ annotations.forEach((annotation) => {
28987
+ const anchorElement = findGutterAnnotationAnchorElementInPage(
28988
+ pageElement,
28989
+ annotation
28990
+ );
28991
+ if (!anchorElement) {
28992
+ return;
28993
+ }
28994
+ const anchorRect = elementRectWithinContainer(
28995
+ anchorElement,
28996
+ pageElement
28997
+ );
28998
+ if (!anchorRect) {
28999
+ return;
29000
+ }
29001
+ const anchorY = clampNumber(
29002
+ Math.round(anchorRect.top + anchorRect.height / 2),
29003
+ 10,
29004
+ Math.max(10, pageHeightPx - 10)
29005
+ );
29006
+ const anchorX = clampNumber(
29007
+ Math.round(anchorRect.right),
29008
+ 10,
29009
+ Math.max(10, pageWidthPx - 10)
29010
+ );
29011
+ anchorsByChangeId.set(annotation.id, { x: anchorX, y: anchorY });
29012
+ });
28768
29013
  return anchorsByChangeId;
28769
29014
  }
28770
- const pageHeightPx = Math.max(1, pageElement.offsetHeight);
28771
- const pageWidthPx = Math.max(1, pageElement.offsetWidth);
28772
- annotations.forEach((annotation) => {
28773
- const anchorElement = findTrackedChangeAnchorElementInPage(
28774
- pageElement,
28775
- annotation.location
28776
- );
28777
- if (!anchorElement) {
28778
- return;
28779
- }
28780
- const anchorRect = elementRectWithinContainer(
28781
- anchorElement,
28782
- pageElement
28783
- );
28784
- if (!anchorRect) {
28785
- return;
28786
- }
28787
- const anchorY = clampNumber(
28788
- Math.round(anchorRect.top + anchorRect.height / 2),
28789
- 10,
28790
- Math.max(10, pageHeightPx - 10)
28791
- );
28792
- const anchorX = clampNumber(
28793
- Math.round(
28794
- anchorRect.left + Math.min(24, Math.max(8, anchorRect.width * 0.2))
28795
- ),
28796
- 10,
28797
- Math.max(10, pageWidthPx - 10)
28798
- );
28799
- anchorsByChangeId.set(annotation.id, { x: anchorX, y: anchorY });
28800
- });
28801
- return anchorsByChangeId;
28802
- });
29015
+ );
28803
29016
  setTrackedChangeAnchorByPage(nextAnchorMaps);
28804
29017
  }, [
28805
29018
  trackedChangesByPage,
@@ -42650,6 +42863,7 @@ ${currentText.slice(end)}`;
42650
42863
  });
42651
42864
  const headerFooterBodyDimmed = pageHeaderFooterEditActive;
42652
42865
  const documentPageBackgroundColor = editor.model.metadata.documentBackgroundColor;
42866
+ const resolvedPageSurfaceBackgroundColor = pageBackgroundColor ?? documentPageBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor;
42653
42867
  const pageBorders = parseSectionPageBorders(
42654
42868
  pageInfo?.section.sectionPropertiesXml ?? editor.model.metadata.sectionPropertiesXml
42655
42869
  );
@@ -42672,7 +42886,7 @@ ${currentText.slice(end)}`;
42672
42886
  width: pageLayout.pageWidthPx,
42673
42887
  height: pageLayout.pageHeightPx,
42674
42888
  minHeight: pageLayout.pageHeightPx,
42675
- backgroundColor: pageBackgroundColor ?? documentPageBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor,
42889
+ backgroundColor: resolvedPageSurfaceBackgroundColor,
42676
42890
  position: "relative",
42677
42891
  ...pageMarginPaddingStyle(pageLayout.marginsPx)
42678
42892
  };
@@ -43774,6 +43988,7 @@ ${currentText.slice(end)}`;
43774
43988
  top: 0,
43775
43989
  width: TRACKED_CHANGE_GUTTER_WIDTH_PX,
43776
43990
  height: pageLayout.pageHeightPx,
43991
+ backgroundColor: resolvedPageSurfaceBackgroundColor,
43777
43992
  pointerEvents: "none",
43778
43993
  overflow: "visible"
43779
43994
  },
@@ -43804,14 +44019,14 @@ ${currentText.slice(end)}`;
43804
44019
  overflow: "visible"
43805
44020
  },
43806
44021
  children: pageTrackedChanges.map((entry) => {
43807
- const accentColor = entry.annotation.trackedChange ? trackedChangeAccentColor(
43808
- entry.annotation.trackedChange.kind,
44022
+ const trackedChange = entry.annotation.trackedChange;
44023
+ const comment = entry.annotation.comment;
44024
+ const accentColor = trackedChange ? trackedChangeAccentColor(
44025
+ trackedChange.kind,
43809
44026
  editor.documentTheme
43810
- ) : commentAccentColor(editor.documentTheme);
43811
- const cardCenterY = clampNumber(
43812
- Math.round(entry.top + entry.heightPx / 2),
43813
- 8,
43814
- Math.max(8, pageLayout.pageHeightPx - 8)
44027
+ ) : commentAccentColor(
44028
+ editor.documentTheme,
44029
+ comment?.commentId
43815
44030
  );
43816
44031
  const anchorY = clampNumber(
43817
44032
  Math.round(entry.anchorY),
@@ -43823,48 +44038,58 @@ ${currentText.slice(end)}`;
43823
44038
  8,
43824
44039
  Math.max(8, pageLayout.pageWidthPx - 8)
43825
44040
  );
43826
- const cardLeadX = pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_CARD_LEFT_PX - 6;
43827
- const bendX = clampNumber(
43828
- Math.round((anchorX + cardLeadX) / 2),
43829
- anchorX + 8,
43830
- Math.max(anchorX + 8, cardLeadX - 8)
44041
+ const cardAttachX = pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_CARD_LEFT_PX;
44042
+ const maxConnectorLaneOffset = Math.max(
44043
+ TRACKED_CHANGE_GUTTER_BEND_OFFSET_PX,
44044
+ TRACKED_CHANGE_GUTTER_CARD_LEFT_PX - 6
44045
+ );
44046
+ const connectorLaneOffset = Math.min(
44047
+ TRACKED_CHANGE_GUTTER_BEND_OFFSET_PX + Math.max(0, entry.connectorLane) * TRACKED_CHANGE_GUTTER_CONNECTOR_LANE_GAP_PX,
44048
+ maxConnectorLaneOffset
44049
+ );
44050
+ const gutterBendX = pageLayout.pageWidthPx + connectorLaneOffset;
44051
+ const cardCenterY = clampNumber(
44052
+ Math.round(entry.top + entry.heightPx / 2),
44053
+ 8,
44054
+ Math.max(8, pageLayout.pageHeightPx - 8)
44055
+ );
44056
+ const connectorPath = Math.abs(cardCenterY - anchorY) <= 2 ? `M ${anchorX} ${anchorY} H ${cardAttachX}` : `M ${anchorX} ${anchorY} H ${gutterBendX} V ${cardCenterY} H ${cardAttachX}`;
44057
+ const revisionBarX = clampNumber(
44058
+ Math.round(pageLayout.marginsPx.left - 20),
44059
+ 8,
44060
+ Math.max(8, pageLayout.pageWidthPx - 8)
43831
44061
  );
43832
44062
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
43833
44063
  "g",
43834
44064
  {
43835
44065
  children: [
44066
+ trackedChange ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
44067
+ "line",
44068
+ {
44069
+ x1: revisionBarX,
44070
+ y1: Math.max(8, anchorY - 16),
44071
+ x2: revisionBarX,
44072
+ y2: Math.min(
44073
+ pageLayout.pageHeightPx - 8,
44074
+ anchorY + 16
44075
+ ),
44076
+ stroke: editor.documentTheme === "dark" ? "#94a3b8" : "#9ca3af",
44077
+ strokeWidth: 1.25,
44078
+ strokeLinecap: "square"
44079
+ }
44080
+ ) : null,
43836
44081
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43837
44082
  "path",
43838
44083
  {
43839
- d: `M ${anchorX} ${anchorY} L ${bendX} ${anchorY} L ${cardLeadX} ${cardCenterY}`,
44084
+ d: connectorPath,
43840
44085
  stroke: accentColor,
43841
- strokeWidth: 1.75,
43842
- strokeOpacity: 1,
43843
- strokeDasharray: "5 4",
44086
+ strokeWidth: 1.15,
44087
+ strokeOpacity: 0.78,
44088
+ strokeDasharray: "2 3",
43844
44089
  strokeLinejoin: "round",
43845
44090
  strokeLinecap: "round",
43846
44091
  fill: "none"
43847
44092
  }
43848
- ),
43849
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43850
- "circle",
43851
- {
43852
- cx: anchorX,
43853
- cy: anchorY,
43854
- r: 2.2,
43855
- fill: accentColor,
43856
- stroke: editor.documentTheme === "dark" ? "#020617" : "#ffffff",
43857
- strokeWidth: 1
43858
- }
43859
- ),
43860
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43861
- "circle",
43862
- {
43863
- cx: cardLeadX,
43864
- cy: cardCenterY,
43865
- r: 1.8,
43866
- fill: accentColor
43867
- }
43868
44093
  )
43869
44094
  ]
43870
44095
  },
@@ -43895,7 +44120,10 @@ ${currentText.slice(end)}`;
43895
44120
  const accentColor = trackedChange ? trackedChangeAccentColor(
43896
44121
  trackedChange.kind,
43897
44122
  editor.documentTheme
43898
- ) : commentAccentColor(editor.documentTheme);
44123
+ ) : commentAccentColor(
44124
+ editor.documentTheme,
44125
+ comment?.commentId
44126
+ );
43899
44127
  const formattedDate = formatTrackedChangeDate(
43900
44128
  trackedChange?.date ?? comment?.date
43901
44129
  );
@@ -43922,15 +44150,15 @@ ${currentText.slice(end)}`;
43922
44150
  {
43923
44151
  style: {
43924
44152
  ...cardStyle,
43925
- padding: "6px 8px",
44153
+ padding: "4px 6px",
43926
44154
  boxSizing: "border-box",
43927
- borderLeft: `2px solid ${accentColor}`,
43928
- borderTop: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.28)" : "rgba(15, 23, 42, 0.12)"}`,
43929
- borderRight: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.28)" : "rgba(15, 23, 42, 0.12)"}`,
43930
- borderBottom: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.28)" : "rgba(15, 23, 42, 0.12)"}`,
43931
- backgroundColor: editor.documentTheme === "dark" ? "rgba(2, 6, 23, 0.96)" : "rgba(255, 255, 255, 0.96)",
44155
+ borderLeft: `1.5px solid ${accentColor}`,
44156
+ borderTop: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.18)" : "rgba(15, 23, 42, 0.08)"}`,
44157
+ borderRight: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.18)" : "rgba(15, 23, 42, 0.08)"}`,
44158
+ borderBottom: `1px solid ${editor.documentTheme === "dark" ? "rgba(148, 163, 184, 0.18)" : "rgba(15, 23, 42, 0.08)"}`,
44159
+ backgroundColor: editor.documentTheme === "dark" ? "rgba(15, 23, 42, 0.92)" : "rgba(255, 255, 255, 0.72)",
43932
44160
  color: editor.documentTheme === "dark" ? "#f3f4f6" : "#111827",
43933
- boxShadow: editor.documentTheme === "dark" ? "0 2px 6px rgba(2, 6, 23, 0.55)" : "0 1px 2px rgba(15, 23, 42, 0.14)"
44161
+ boxShadow: editor.documentTheme === "dark" ? "0 1px 2px rgba(2, 6, 23, 0.45)" : "0 1px 1px rgba(15, 23, 42, 0.08)"
43934
44162
  },
43935
44163
  children: [
43936
44164
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
@@ -43948,9 +44176,9 @@ ${currentText.slice(end)}`;
43948
44176
  {
43949
44177
  style: {
43950
44178
  margin: 0,
43951
- fontSize: 12,
44179
+ fontSize: 10,
43952
44180
  fontWeight: 700,
43953
- lineHeight: 1.25
44181
+ lineHeight: 1.2
43954
44182
  },
43955
44183
  children: (trackedChange?.author ?? comment?.author)?.trim() || "Unknown author"
43956
44184
  }
@@ -43960,8 +44188,8 @@ ${currentText.slice(end)}`;
43960
44188
  {
43961
44189
  style: {
43962
44190
  margin: 0,
43963
- fontSize: 11,
43964
- lineHeight: 1.2,
44191
+ fontSize: 9,
44192
+ lineHeight: 1.15,
43965
44193
  color: editor.documentTheme === "dark" ? "#94a3b8" : "#6b7280",
43966
44194
  whiteSpace: "nowrap"
43967
44195
  },
@@ -43976,8 +44204,8 @@ ${currentText.slice(end)}`;
43976
44204
  {
43977
44205
  style: {
43978
44206
  margin: "2px 0 0",
43979
- fontSize: 11,
43980
- lineHeight: 1.3,
44207
+ fontSize: 9,
44208
+ lineHeight: 1.25,
43981
44209
  fontStyle: "italic",
43982
44210
  color: editor.documentTheme === "dark" ? "#94a3b8" : "#6b7280"
43983
44211
  },
@@ -43993,8 +44221,8 @@ ${currentText.slice(end)}`;
43993
44221
  {
43994
44222
  style: {
43995
44223
  margin: "2px 0 0",
43996
- fontSize: 12,
43997
- lineHeight: 1.35
44224
+ fontSize: 10,
44225
+ lineHeight: 1.25
43998
44226
  },
43999
44227
  children: [
44000
44228
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
@@ -44031,6 +44259,10 @@ ${currentText.slice(end)}`;
44031
44259
  "div",
44032
44260
  {
44033
44261
  "data-docx-gutter-annotation": trackedChange ? "tracked-change" : "comment",
44262
+ "data-docx-gutter-annotation-id": entry.annotation.id,
44263
+ "data-docx-gutter-anchor-x": Math.round(entry.anchorX),
44264
+ "data-docx-gutter-anchor-y": Math.round(entry.anchorY),
44265
+ "data-docx-gutter-connector-lane": entry.connectorLane,
44034
44266
  ref: (element) => {
44035
44267
  const elementKey = `${pageIndex}:${entry.annotation.id}`;
44036
44268
  if (element) {