@atlaskit/editor-plugin-show-diff 10.5.0 → 10.5.2

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.
Files changed (27) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +30 -3
  3. package/dist/cjs/pm-plugins/decorations/colorSchemes/standard.js +14 -1
  4. package/dist/cjs/pm-plugins/decorations/colorSchemes/traditional.js +15 -2
  5. package/dist/cjs/pm-plugins/decorations/createAnchorDecorationWidgets.js +52 -18
  6. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +6 -1
  7. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +23 -4
  8. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +64 -4
  9. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +30 -3
  10. package/dist/es2019/pm-plugins/decorations/colorSchemes/standard.js +13 -0
  11. package/dist/es2019/pm-plugins/decorations/colorSchemes/traditional.js +14 -1
  12. package/dist/es2019/pm-plugins/decorations/createAnchorDecorationWidgets.js +60 -28
  13. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +8 -3
  14. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +16 -1
  15. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +53 -4
  16. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +30 -3
  17. package/dist/esm/pm-plugins/decorations/colorSchemes/standard.js +13 -0
  18. package/dist/esm/pm-plugins/decorations/colorSchemes/traditional.js +14 -1
  19. package/dist/esm/pm-plugins/decorations/createAnchorDecorationWidgets.js +51 -18
  20. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +8 -3
  21. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +23 -4
  22. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +63 -4
  23. package/dist/types/pm-plugins/decorations/colorSchemes/standard.d.ts +1 -0
  24. package/dist/types/pm-plugins/decorations/colorSchemes/traditional.d.ts +2 -1
  25. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +4 -1
  26. package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +11 -1
  27. package/package.json +7 -7
@@ -136,6 +136,7 @@ export const createLeftAnchorWidget = ({
136
136
  diffId,
137
137
  anchorType: AnchorTypeKey.left
138
138
  });
139
+ let leftResizeObserver;
139
140
  return Decoration.widget(beforePos, (view, getPos) => {
140
141
  // Outer span stays in the flow but takes up no space.
141
142
  const wrapper = document.createElement('div');
@@ -150,13 +151,7 @@ export const createLeftAnchorWidget = ({
150
151
  anchor.style.setProperty('left', `calc(50% - ${(edgeCase === null || edgeCase === void 0 ? void 0 : edgeCase.leftOffset) || 0}px)`);
151
152
  anchor.style.setProperty('transform', 'translateX(-50%)');
152
153
  wrapper.appendChild(anchor);
153
-
154
- // The block DOM may not be settled synchronously (e.g. after a
155
- // transaction), so defer the measurement like the gap cursor does.
156
- requestAnimationFrame(() => {
157
- // The widget may have been unmounted; bail if its position is gone.
158
- // We still measure the stable block node position, not the widget's
159
- // own position.
154
+ const measureWidth = () => {
160
155
  if (getPos() === undefined || edgeCase.measurePos === undefined) {
161
156
  return;
162
157
  }
@@ -165,14 +160,35 @@ export const createLeftAnchorWidget = ({
165
160
  // The left anchor only needs the container width so the
166
161
  // IndicatorBar can align against the block's horizontal extent.
167
162
  anchor.style.setProperty('width', `${dom.offsetWidth}px`);
163
+
164
+ // Observe the measured element for size changes (e.g. page
165
+ // resize) so the indicator stays aligned. CCI-17981
166
+ if (!leftResizeObserver) {
167
+ leftResizeObserver = new ResizeObserver(() => {
168
+ if (getPos() !== undefined) {
169
+ anchor.style.setProperty('width', `${dom.offsetWidth}px`);
170
+ }
171
+ });
172
+ leftResizeObserver.observe(dom);
173
+ }
168
174
  }
169
- });
175
+ };
176
+
177
+ // The block DOM may not be settled synchronously (e.g. after a
178
+ // transaction), so defer the measurement like the gap cursor does.
179
+ requestAnimationFrame(measureWidth);
170
180
  return wrapper;
171
- }, buildAnchorDecorationSpec({
172
- diffId,
173
- anchorType: AnchorTypeKey.left,
174
- side: -999
175
- }));
181
+ }, {
182
+ ...buildAnchorDecorationSpec({
183
+ diffId,
184
+ anchorType: AnchorTypeKey.left,
185
+ side: -999
186
+ }),
187
+ destroy: () => {
188
+ var _leftResizeObserver;
189
+ return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.disconnect();
190
+ }
191
+ });
176
192
  };
177
193
 
178
194
  /**
@@ -229,6 +245,7 @@ export const createBlockIndicatorAnchorWidgets = ({
229
245
  // Measure the actual cell/row DOM when inside one; otherwise measure the
230
246
  // widget's own position.
231
247
  const measurePos = parentCellOrRow ? parentCellOrRow.pos : from;
248
+ let blockResizeObserver;
232
249
  const blockWidget = Decoration.widget(widgetPos, (view, getPos) => {
233
250
  // Outer span stays in the flow but takes up no space.
234
251
  const wrapper = document.createElement('span');
@@ -240,13 +257,7 @@ export const createBlockIndicatorAnchorWidgets = ({
240
257
  anchor.style.setProperty('position', 'absolute');
241
258
  anchor.style.setProperty('anchor-name', `--${blockAnchorKey}`);
242
259
  wrapper.appendChild(anchor);
243
-
244
- // The block DOM may not be settled synchronously (e.g. after a
245
- // transaction), so defer the measurement like the gap cursor does.
246
- requestAnimationFrame(() => {
247
- // The widget may have been unmounted; bail if its position is gone.
248
- // We still measure the stable cell/row node position, not the
249
- // widget's own position.
260
+ const measureBlock = () => {
250
261
  if (getPos() === undefined) {
251
262
  return;
252
263
  }
@@ -265,16 +276,37 @@ export const createBlockIndicatorAnchorWidgets = ({
265
276
  // The offset already accounts for the cell/row's position, so the
266
277
  // margin-top must not be double-applied.
267
278
  anchor.style.setProperty('margin-top', '0px');
279
+
280
+ // Observe the measured element for size changes (e.g. page
281
+ // resize) so the indicator stays aligned. CCI-17981
282
+ if (!blockResizeObserver) {
283
+ blockResizeObserver = new ResizeObserver(() => {
284
+ if (getPos() !== undefined) {
285
+ measureBlock();
286
+ }
287
+ });
288
+ blockResizeObserver.observe(dom);
289
+ }
268
290
  }
269
- });
291
+ };
292
+
293
+ // The block DOM may not be settled synchronously (e.g. after a
294
+ // transaction), so defer the measurement like the gap cursor does.
295
+ requestAnimationFrame(measureBlock);
270
296
  return wrapper;
271
- }, buildAnchorDecorationSpec({
272
- diffId,
273
- // Reuse the `from` anchor type slot; the generated key intentionally
274
- // omits the anchor type so the single element backs top/bottom/left.
275
- anchorType: AnchorTypeKey.from,
276
- side: -1
277
- }));
297
+ }, {
298
+ ...buildAnchorDecorationSpec({
299
+ diffId,
300
+ // Reuse the `from` anchor type slot; the generated key intentionally
301
+ // omits the anchor type so the single element backs top/bottom/left.
302
+ anchorType: AnchorTypeKey.from,
303
+ side: -1
304
+ }),
305
+ destroy: () => {
306
+ var _blockResizeObserver;
307
+ return (_blockResizeObserver = blockResizeObserver) === null || _blockResizeObserver === void 0 ? void 0 : _blockResizeObserver.disconnect();
308
+ }
309
+ });
278
310
  return [blockWidget, ...maybeLeftAnchor];
279
311
  };
280
312
 
@@ -1,8 +1,9 @@
1
1
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
4
  import { isExtendedEnabled } from '../isExtendedEnabled';
4
- import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle } from './colorSchemes/standard';
5
- import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle } from './colorSchemes/traditional';
5
+ import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle, deletedCellOverlayRoundedStyle } from './colorSchemes/standard';
6
+ import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle, deletedTraditionalCellOverlayRoundedStyle } from './colorSchemes/traditional';
6
7
  import { createBlockIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
7
8
  import { buildDiffDecorationSpec } from './decorationKeys';
8
9
  const displayNoneStyle = convertToInlineCss({
@@ -143,7 +144,11 @@ export const createBlockChangedDecoration = ({
143
144
  let style;
144
145
  if (isExtendedEnabled(diffType) && ['tableCell', 'tableHeader'].includes(change.name)) {
145
146
  const cellOverlay = document.createElement('div');
146
- const cellOverlayStyle = isInserted ? colorScheme === 'traditional' ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle : colorScheme === 'traditional' ? deletedTraditionalCellOverlayStyle : deletedCellOverlayStyle;
147
+ const isTraditional = colorScheme === 'traditional';
148
+ const isRoundedTable = expValEquals('platform_editor_table_diff_rounded_corners', 'isEnabled', true);
149
+ const addedCellStyle = isTraditional ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle;
150
+ const deletedCellStyle = isTraditional ? isRoundedTable ? deletedTraditionalCellOverlayRoundedStyle : deletedTraditionalCellOverlayStyle : isRoundedTable ? deletedCellOverlayRoundedStyle : deletedCellOverlayStyle;
151
+ const cellOverlayStyle = isInserted ? addedCellStyle : deletedCellStyle;
147
152
  cellOverlay.setAttribute('style', cellOverlayStyle);
148
153
  decorations.push(
149
154
  // change.to - 1 to position the overlay inside the end of the cell
@@ -8,6 +8,16 @@ import { buildDiffDecorationSpec } from './decorationKeys';
8
8
  const displayNoneStyle = convertToInlineCss({
9
9
  display: 'none'
10
10
  });
11
+ const getAtomicInlineNodeClassName = (inlineNodeName, colorScheme) => {
12
+ const classNames = ['show-diff-atomic-inline-changed'];
13
+ if (inlineNodeName) {
14
+ classNames.push(`show-diff-atomic-inline-changed-${inlineNodeName}`);
15
+ }
16
+ if (colorScheme === 'traditional') {
17
+ classNames.push('show-diff-atomic-inline-changed-traditional');
18
+ }
19
+ return classNames.join(' ');
20
+ };
11
21
  /**
12
22
  * Inline decoration used for insertions as the content already exists in the document
13
23
  *
@@ -20,11 +30,13 @@ export const createInlineChangedDecoration = ({
20
30
  colorScheme,
21
31
  isActive = false,
22
32
  isInserted = true,
33
+ isAtomicInlineNode = false,
23
34
  shouldHideDeleted = false,
24
35
  showIndicators = false,
25
36
  doc,
26
37
  diffType,
27
- hideAddedDiffsUnderline = false
38
+ hideAddedDiffsUnderline = false,
39
+ inlineNodeName
28
40
  }) => {
29
41
  const diffId = crypto.randomUUID();
30
42
  if (shouldHideDeleted) {
@@ -66,6 +78,9 @@ export const createInlineChangedDecoration = ({
66
78
  }
67
79
  const decorations = [Decoration.inline(change.fromB, change.toB, {
68
80
  style,
81
+ ...(isAtomicInlineNode && isInserted && {
82
+ class: getAtomicInlineNodeClassName(inlineNodeName, colorScheme)
83
+ }),
69
84
  'data-testid': 'show-diff-changed-decoration'
70
85
  }, buildDiffDecorationSpec({
71
86
  decorationType: 'inline',
@@ -1,5 +1,6 @@
1
1
  import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
2
2
  import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
3
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
4
  const filterUndefined = x => !!x;
4
5
 
5
6
  // Attributes that indicate a change in media image
@@ -11,6 +12,24 @@ const dateAttrs = ['timestamp'];
11
12
  // Attribute that indicates a task item state change
12
13
  const taskItemAttrs = ['state'];
13
14
 
15
+ // Attributes that indicate an emoji change
16
+ const emojiAttrs = ['shortName', 'id', 'text'];
17
+
18
+ // Attributes that indicate a mention change (who is mentioned)
19
+ const mentionAttrs = ['id', 'text'];
20
+
21
+ // Attributes that indicate a status change (label or colour)
22
+ const statusAttrs = ['text', 'color'];
23
+
24
+ // Map of node type name → the attrs that represent a meaningful content change for that node
25
+ const inlineNodeAttrMap = {
26
+ date: dateAttrs,
27
+ emoji: emojiAttrs,
28
+ mention: mentionAttrs,
29
+ status: statusAttrs
30
+ };
31
+ const isInlineAttrChangeNodeName = nodeName => nodeName in inlineNodeAttrMap;
32
+
14
33
  // Attributes excluded from extension change detection (not meaningful content changes)
15
34
  const extensionExcludedAttrs = ['localId'];
16
35
 
@@ -25,7 +44,7 @@ const getStepAttrs = step => {
25
44
  }
26
45
  return [];
27
46
  };
28
- export const getAttrChangeRanges = (doc, steps) => {
47
+ export const getAttrChangeRanges = (doc, steps, originalDoc) => {
29
48
  return steps.map(step => {
30
49
  if (!(step instanceof AttrStep) && !(step instanceof SetAttrsStep)) {
31
50
  return undefined;
@@ -35,14 +54,38 @@ export const getAttrChangeRanges = (doc, steps) => {
35
54
  const nodeAtPos = doc.nodeAt(step.pos);
36
55
 
37
56
  // date node: timestamp attribute change — highlight the date node itself (inline)
38
- if (stepAttrs.some(v => dateAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date') {
57
+ if (stepAttrs.some(v => dateAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
39
58
  return {
40
59
  fromB: step.pos,
41
60
  toB: step.pos + nodeAtPos.nodeSize,
42
- isInline: true
61
+ isInline: true,
62
+ inlineNodeName: 'date'
43
63
  };
44
64
  }
45
65
 
66
+ // The following inline node attr changes are gated behind platform_editor_improve_inline_diffs.
67
+ // The changeset path (createDecorationsForChange) handles the deletion widget via
68
+ // prosemirror-changeset; we only need to add the inline insertion highlight here.
69
+ if (expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true) && nodeAtPos) {
70
+ const nodeName = nodeAtPos.type.name;
71
+ if (isInlineAttrChangeNodeName(nodeName)) {
72
+ const watchedAttrs = inlineNodeAttrMap[nodeName];
73
+ if (stepAttrs.some(v => watchedAttrs.includes(v))) {
74
+ const originalNodeAtPos = originalDoc === null || originalDoc === void 0 ? void 0 : originalDoc.nodeAt(step.pos);
75
+ return {
76
+ fromB: step.pos,
77
+ toB: step.pos + nodeAtPos.nodeSize,
78
+ isInline: true,
79
+ inlineNodeName: nodeName,
80
+ ...(originalNodeAtPos && {
81
+ fromA: step.pos,
82
+ toA: step.pos + originalNodeAtPos.nodeSize
83
+ })
84
+ };
85
+ }
86
+ }
87
+ }
88
+
46
89
  // taskItem node: state attribute change — highlight the taskItem node
47
90
  if (stepAttrs.some(v => taskItemAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'taskItem') {
48
91
  return {
@@ -70,7 +113,13 @@ export const getAttrChangeRanges = (doc, steps) => {
70
113
  };
71
114
  }
72
115
  return undefined;
73
- }).filter(filterUndefined);
116
+ }).filter(filterUndefined)
117
+ // Deduplicate by node position: multiple AttrSteps on the same node
118
+ // (e.g. setNodeAttribute(pos, 'text', ...) + setNodeAttribute(pos, 'color', ...))
119
+ // should produce only one decoration, not one per step.
120
+ // Gated behind the same experiment as the inline node attr changes that introduced
121
+ // the possibility of multiple ranges for the same node position.
122
+ .filter((range, i, arr) => !expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true) || arr.findIndex(r => r.fromB === range.fromB) === i);
74
123
  };
75
124
 
76
125
  /**
@@ -421,16 +421,43 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
421
421
  isInserted: true
422
422
  })));
423
423
  });
424
- getAttrChangeRanges(tr.doc, attrSteps).forEach(function (change) {
424
+ getAttrChangeRanges(tr.doc, attrSteps, originalDoc).forEach(function (change) {
425
425
  if (change.isInline) {
426
- // Inline nodes (e.g. date) need an inline decoration rather than a block decoration
426
+ // Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
427
427
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
428
+ var isAtomicInlineNodeFlag = expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
428
429
  decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration({
429
430
  change: change,
430
431
  colorScheme: colorScheme,
431
432
  isActive: isActive,
432
- isInserted: true
433
+ isInserted: true,
434
+ isAtomicInlineNode: isAtomicInlineNodeFlag,
435
+ inlineNodeName: change.inlineNodeName,
436
+ // Suppress the border-bottom underline for atomic inline nodeviews —
437
+ // it doesn't render on custom nodeview DOM elements and is unnecessary noise.
438
+ hideAddedDiffsUnderline: isAtomicInlineNodeFlag,
439
+ diffType: diffType
433
440
  })));
441
+ // If we have the original node position, also render the old node as a "deleted" widget
442
+ // so the user can see what it looked like before the change.
443
+ if (change.fromA !== undefined && change.toA !== undefined && expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
444
+ decorations.push.apply(decorations, _toConsumableArray(createNodeChangedDecorationWidget({
445
+ change: {
446
+ fromA: change.fromA,
447
+ toA: change.toA,
448
+ fromB: change.fromB,
449
+ toB: change.toB,
450
+ deleted: []
451
+ },
452
+ doc: originalDoc,
453
+ nodeViewSerializer: nodeViewSerializer,
454
+ colorScheme: colorScheme,
455
+ newDoc: tr.doc,
456
+ intl: intl,
457
+ activeIndexPos: activeIndexPos,
458
+ isInserted: false
459
+ })));
460
+ }
434
461
  } else {
435
462
  decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration({
436
463
  doc: tr.doc,
@@ -180,4 +180,17 @@ export var deletedCellOverlayStyle = convertToInlineCss({
180
180
  zIndex: 1,
181
181
  outline: "1px solid ".concat("var(--ds-border-accent-gray, #7D818A)"),
182
182
  pointerEvents: 'none'
183
+ });
184
+ export var deletedCellOverlayRoundedStyle = convertToInlineCss({
185
+ position: 'absolute',
186
+ top: 0,
187
+ left: 0,
188
+ width: '100%',
189
+ height: '100%',
190
+ backgroundColor: "rgba(from ".concat("var(--ds-background-accent-gray-subtlest, #F0F1F2)", " r g b / 0.5)"),
191
+ zIndex: 2,
192
+ outline: "1px solid ".concat("var(--ds-border-accent-gray, #7D818A)"),
193
+ pointerEvents: 'none',
194
+ border: 'inherit',
195
+ borderRadius: 'inherit'
183
196
  });
@@ -84,7 +84,7 @@ export var deletedTraditionalBlockOutlineRoundedActive = convertToInlineCss({
84
84
  borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
85
85
  });
86
86
 
87
- /** Scroll-navigation “new” emphasis: 4px ring (see {@link traditionalStyleNodeNew}). */
87
+ /** Scroll-navigation “new” emphasis: 4px ring. */
88
88
  export var deletedTraditionalBlockOutlineNew = convertToInlineCss({
89
89
  boxShadow: "0 0 0 4px ".concat("var(--ds-background-accent-red-subtlest, #FFECEB)"),
90
90
  borderRadius: "var(--ds-radius-small, 4px)"
@@ -205,4 +205,17 @@ export var deletedTraditionalCellOverlayStyle = convertToInlineCss({
205
205
  zIndex: 1,
206
206
  outline: "1px solid ".concat("var(--ds-border-disabled, #0515240F)"),
207
207
  pointerEvents: 'none'
208
+ });
209
+ export var deletedTraditionalCellOverlayRoundedStyle = convertToInlineCss({
210
+ position: 'absolute',
211
+ top: 0,
212
+ left: 0,
213
+ width: '100%',
214
+ height: '100%',
215
+ backgroundColor: "rgba(from ".concat("var(--ds-background-accent-gray-subtlest, #F0F1F2)", " r g b / 0.5)"),
216
+ zIndex: 2,
217
+ outline: "1px solid ".concat("var(--ds-border-disabled, #0515240F)"),
218
+ pointerEvents: 'none',
219
+ border: 'inherit',
220
+ borderRadius: 'inherit'
208
221
  });
@@ -1,3 +1,6 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1
4
  import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
2
5
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
6
  import { buildAnchorDecorationKey, buildAnchorDecorationSpec, AnchorDocMarginKey, AnchorTypeKey } from './decorationKeys';
@@ -133,6 +136,7 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
133
136
  diffId: diffId,
134
137
  anchorType: AnchorTypeKey.left
135
138
  });
139
+ var leftResizeObserver;
136
140
  return Decoration.widget(beforePos, function (view, getPos) {
137
141
  // Outer span stays in the flow but takes up no space.
138
142
  var wrapper = document.createElement('div');
@@ -147,13 +151,7 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
147
151
  anchor.style.setProperty('left', "calc(50% - ".concat((edgeCase === null || edgeCase === void 0 ? void 0 : edgeCase.leftOffset) || 0, "px)"));
148
152
  anchor.style.setProperty('transform', 'translateX(-50%)');
149
153
  wrapper.appendChild(anchor);
150
-
151
- // The block DOM may not be settled synchronously (e.g. after a
152
- // transaction), so defer the measurement like the gap cursor does.
153
- requestAnimationFrame(function () {
154
- // The widget may have been unmounted; bail if its position is gone.
155
- // We still measure the stable block node position, not the widget's
156
- // own position.
154
+ var measureWidth = function measureWidth() {
157
155
  if (getPos() === undefined || edgeCase.measurePos === undefined) {
158
156
  return;
159
157
  }
@@ -162,13 +160,33 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
162
160
  // The left anchor only needs the container width so the
163
161
  // IndicatorBar can align against the block's horizontal extent.
164
162
  anchor.style.setProperty('width', "".concat(dom.offsetWidth, "px"));
163
+
164
+ // Observe the measured element for size changes (e.g. page
165
+ // resize) so the indicator stays aligned. CCI-17981
166
+ if (!leftResizeObserver) {
167
+ leftResizeObserver = new ResizeObserver(function () {
168
+ if (getPos() !== undefined) {
169
+ anchor.style.setProperty('width', "".concat(dom.offsetWidth, "px"));
170
+ }
171
+ });
172
+ leftResizeObserver.observe(dom);
173
+ }
165
174
  }
166
- });
175
+ };
176
+
177
+ // The block DOM may not be settled synchronously (e.g. after a
178
+ // transaction), so defer the measurement like the gap cursor does.
179
+ requestAnimationFrame(measureWidth);
167
180
  return wrapper;
168
- }, buildAnchorDecorationSpec({
181
+ }, _objectSpread(_objectSpread({}, buildAnchorDecorationSpec({
169
182
  diffId: diffId,
170
183
  anchorType: AnchorTypeKey.left,
171
184
  side: -999
185
+ })), {}, {
186
+ destroy: function destroy() {
187
+ var _leftResizeObserver;
188
+ return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.disconnect();
189
+ }
172
190
  }));
173
191
  };
174
192
 
@@ -229,6 +247,7 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
229
247
  // Measure the actual cell/row DOM when inside one; otherwise measure the
230
248
  // widget's own position.
231
249
  var measurePos = parentCellOrRow ? parentCellOrRow.pos : from;
250
+ var blockResizeObserver;
232
251
  var blockWidget = Decoration.widget(widgetPos, function (view, getPos) {
233
252
  // Outer span stays in the flow but takes up no space.
234
253
  var wrapper = document.createElement('span');
@@ -240,13 +259,7 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
240
259
  anchor.style.setProperty('position', 'absolute');
241
260
  anchor.style.setProperty('anchor-name', "--".concat(blockAnchorKey));
242
261
  wrapper.appendChild(anchor);
243
-
244
- // The block DOM may not be settled synchronously (e.g. after a
245
- // transaction), so defer the measurement like the gap cursor does.
246
- requestAnimationFrame(function () {
247
- // The widget may have been unmounted; bail if its position is gone.
248
- // We still measure the stable cell/row node position, not the
249
- // widget's own position.
262
+ var _measureBlock = function measureBlock() {
250
263
  if (getPos() === undefined) {
251
264
  return;
252
265
  }
@@ -265,15 +278,35 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
265
278
  // The offset already accounts for the cell/row's position, so the
266
279
  // margin-top must not be double-applied.
267
280
  anchor.style.setProperty('margin-top', '0px');
281
+
282
+ // Observe the measured element for size changes (e.g. page
283
+ // resize) so the indicator stays aligned. CCI-17981
284
+ if (!blockResizeObserver) {
285
+ blockResizeObserver = new ResizeObserver(function () {
286
+ if (getPos() !== undefined) {
287
+ _measureBlock();
288
+ }
289
+ });
290
+ blockResizeObserver.observe(dom);
291
+ }
268
292
  }
269
- });
293
+ };
294
+
295
+ // The block DOM may not be settled synchronously (e.g. after a
296
+ // transaction), so defer the measurement like the gap cursor does.
297
+ requestAnimationFrame(_measureBlock);
270
298
  return wrapper;
271
- }, buildAnchorDecorationSpec({
299
+ }, _objectSpread(_objectSpread({}, buildAnchorDecorationSpec({
272
300
  diffId: diffId,
273
301
  // Reuse the `from` anchor type slot; the generated key intentionally
274
302
  // omits the anchor type so the single element backs top/bottom/left.
275
303
  anchorType: AnchorTypeKey.from,
276
304
  side: -1
305
+ })), {}, {
306
+ destroy: function destroy() {
307
+ var _blockResizeObserver;
308
+ return (_blockResizeObserver = blockResizeObserver) === null || _blockResizeObserver === void 0 ? void 0 : _blockResizeObserver.disconnect();
309
+ }
277
310
  }));
278
311
  return [blockWidget].concat(maybeLeftAnchor);
279
312
  };
@@ -1,9 +1,10 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
3
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
5
  import { isExtendedEnabled } from '../isExtendedEnabled';
5
- import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle } from './colorSchemes/standard';
6
- import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle } from './colorSchemes/traditional';
6
+ import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle, deletedCellOverlayRoundedStyle } from './colorSchemes/standard';
7
+ import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle, deletedTraditionalCellOverlayRoundedStyle } from './colorSchemes/traditional';
7
8
  import { createBlockIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
8
9
  import { buildDiffDecorationSpec } from './decorationKeys';
9
10
  var displayNoneStyle = convertToInlineCss({
@@ -148,7 +149,11 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
148
149
  var style;
149
150
  if (isExtendedEnabled(diffType) && ['tableCell', 'tableHeader'].includes(change.name)) {
150
151
  var cellOverlay = document.createElement('div');
151
- var cellOverlayStyle = isInserted ? colorScheme === 'traditional' ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle : colorScheme === 'traditional' ? deletedTraditionalCellOverlayStyle : deletedCellOverlayStyle;
152
+ var isTraditional = colorScheme === 'traditional';
153
+ var isRoundedTable = expValEquals('platform_editor_table_diff_rounded_corners', 'isEnabled', true);
154
+ var addedCellStyle = isTraditional ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle;
155
+ var deletedCellStyle = isTraditional ? isRoundedTable ? deletedTraditionalCellOverlayRoundedStyle : deletedTraditionalCellOverlayStyle : isRoundedTable ? deletedCellOverlayRoundedStyle : deletedCellOverlayStyle;
156
+ var cellOverlayStyle = isInserted ? addedCellStyle : deletedCellStyle;
152
157
  cellOverlay.setAttribute('style', cellOverlayStyle);
153
158
  decorations.push(
154
159
  // change.to - 1 to position the overlay inside the end of the cell
@@ -1,4 +1,7 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
5
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
3
6
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
7
  import { isExtendedEnabled } from '../isExtendedEnabled';
@@ -9,6 +12,16 @@ import { buildDiffDecorationSpec } from './decorationKeys';
9
12
  var displayNoneStyle = convertToInlineCss({
10
13
  display: 'none'
11
14
  });
15
+ var getAtomicInlineNodeClassName = function getAtomicInlineNodeClassName(inlineNodeName, colorScheme) {
16
+ var classNames = ['show-diff-atomic-inline-changed'];
17
+ if (inlineNodeName) {
18
+ classNames.push("show-diff-atomic-inline-changed-".concat(inlineNodeName));
19
+ }
20
+ if (colorScheme === 'traditional') {
21
+ classNames.push('show-diff-atomic-inline-changed-traditional');
22
+ }
23
+ return classNames.join(' ');
24
+ };
12
25
  /**
13
26
  * Inline decoration used for insertions as the content already exists in the document
14
27
  *
@@ -23,6 +36,8 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
23
36
  isActive = _ref$isActive === void 0 ? false : _ref$isActive,
24
37
  _ref$isInserted = _ref.isInserted,
25
38
  isInserted = _ref$isInserted === void 0 ? true : _ref$isInserted,
39
+ _ref$isAtomicInlineNo = _ref.isAtomicInlineNode,
40
+ isAtomicInlineNode = _ref$isAtomicInlineNo === void 0 ? false : _ref$isAtomicInlineNo,
26
41
  _ref$shouldHideDelete = _ref.shouldHideDeleted,
27
42
  shouldHideDeleted = _ref$shouldHideDelete === void 0 ? false : _ref$shouldHideDelete,
28
43
  _ref$showIndicators = _ref.showIndicators,
@@ -30,7 +45,8 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
30
45
  doc = _ref.doc,
31
46
  diffType = _ref.diffType,
32
47
  _ref$hideAddedDiffsUn = _ref.hideAddedDiffsUnderline,
33
- hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn;
48
+ hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn,
49
+ inlineNodeName = _ref.inlineNodeName;
34
50
  var diffId = crypto.randomUUID();
35
51
  if (shouldHideDeleted) {
36
52
  return [Decoration.inline(change.fromB, change.toB, {
@@ -69,10 +85,13 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
69
85
  style = isActive ? editingStyleActive : editingStyle;
70
86
  }
71
87
  }
72
- var decorations = [Decoration.inline(change.fromB, change.toB, {
73
- style: style,
88
+ var decorations = [Decoration.inline(change.fromB, change.toB, _objectSpread(_objectSpread({
89
+ style: style
90
+ }, isAtomicInlineNode && isInserted && {
91
+ class: getAtomicInlineNodeClassName(inlineNodeName, colorScheme)
92
+ }), {}, {
74
93
  'data-testid': 'show-diff-changed-decoration'
75
- }, buildDiffDecorationSpec({
94
+ }), buildDiffDecorationSpec({
76
95
  decorationType: 'inline',
77
96
  diffId: diffId,
78
97
  isActive: isActive