@atlaskit/editor-plugin-show-diff 23.0.3 → 24.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 24.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`37fc21aa0e358`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/37fc21aa0e358) -
8
+ Show contributor tags for layout changes in version history when
9
+ `confluence_ncs_step_diffing_version_history` is enabled
10
+ - Updated dependencies
11
+
12
+ ## 24.0.0
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies
17
+
3
18
  ## 23.0.3
4
19
 
5
20
  ### Patch Changes
@@ -9,6 +9,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
9
9
  var _view = require("@atlaskit/editor-prosemirror/view");
10
10
  var _fg = require("@atlaskit/platform-feature-flags/fg");
11
11
  var _contributorTagController = require("../../ui/ContributorTag/contributorTagController");
12
+ var _baseNodeName = require("../utils/baseNodeName");
12
13
  var _charsByOffset = require("../utils/charsByOffset");
13
14
  var _createAnchorDecorationWidgets = require("./createAnchorDecorationWidgets");
14
15
  var _decorationKeys = require("./decorationKeys");
@@ -219,6 +220,16 @@ var resolveHoistedCodeBlockAnchor = exports.resolveHoistedCodeBlockAnchor = func
219
220
  };
220
221
  };
221
222
 
223
+ /** Find the position before a layout for a tag anchored to one of its columns. */
224
+ var resolveLayoutSectionStart = function resolveLayoutSectionStart(doc, pos) {
225
+ var _doc$nodeAt$type$name, _doc$nodeAt;
226
+ if ((0, _baseNodeName.resolveBaseNodeName)((_doc$nodeAt$type$name = (_doc$nodeAt = doc.nodeAt(pos)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type.name) !== null && _doc$nodeAt$type$name !== void 0 ? _doc$nodeAt$type$name : '') !== 'layoutColumn') {
227
+ return undefined;
228
+ }
229
+ var $pos = doc.resolve(pos);
230
+ return (0, _baseNodeName.resolveBaseNodeName)($pos.parent.type.name) === 'layoutSection' ? $pos.before($pos.depth) : undefined;
231
+ };
232
+
222
233
  /**
223
234
  * The contributor tag widget for one diff range, placed on the first visible character the range
224
235
  * highlights — or, with `anchorAtRangeStart`, at `from` itself. A host inside a code block is
@@ -231,7 +242,7 @@ var resolveHoistedCodeBlockAnchor = exports.resolveHoistedCodeBlockAnchor = func
231
242
  * element ProseMirror drew it into — see `mountContributorTag`.
232
243
  */
233
244
  var createContributorTagWidget = exports.createContributorTagWidget = function createContributorTagWidget(_ref4) {
234
- var _hoisted$codeBlockSta, _ref5, _hoisted$anchorName;
245
+ var _ref5, _hoisted$anchorName, _hoisted$codeBlockSta;
235
246
  var _ref4$anchorAtRangeSt = _ref4.anchorAtRangeStart,
236
247
  anchorAtRangeStart = _ref4$anchorAtRangeSt === void 0 ? false : _ref4$anchorAtRangeSt,
237
248
  anchorName = _ref4.anchorName,
@@ -251,8 +262,6 @@ var createContributorTagWidget = exports.createContributorTagWidget = function c
251
262
  // A change inside a code block is hoisted out of it, anchored to its own marker; anything else
252
263
  // keeps its own anchor.
253
264
  var hoisted = resolveHoistedCodeBlockAnchor(doc, anchorPos, diffId);
254
- // Keep the host out of the table row's grid (EDITOR-8442).
255
- var hostPos = (0, _createAnchorDecorationWidgets.clampAnchorPosIntoCell)(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
256
265
 
257
266
  // Inline diffs pass no anchorName. Give them their own point anchor instead of the
258
267
  // `position: relative` fallback, which drifts left once the range wraps a line (EDITOR-9286).
@@ -262,6 +271,10 @@ var createContributorTagWidget = exports.createContributorTagWidget = function c
262
271
  });
263
272
  var effectiveAnchorName = (_ref5 = (_hoisted$anchorName = hoisted === null || hoisted === void 0 ? void 0 : hoisted.anchorName) !== null && _hoisted$anchorName !== void 0 ? _hoisted$anchorName : anchorName) !== null && _ref5 !== void 0 ? _ref5 : ownAnchorName;
264
273
  var tagAnchorName = effectiveAnchorName && supportsAnchorPositioning() ? effectiveAnchorName : undefined;
274
+ var layoutSectionStart = tagAnchorName ? resolveLayoutSectionStart(doc, anchorPos) : undefined;
275
+ // Keep the host out of the table row's grid (EDITOR-8442). Layout-column tags are hoisted before
276
+ // their layout so the advanced layout widget-flattening rule cannot put them behind nearby text.
277
+ var hostPos = layoutSectionStart !== null && layoutSectionStart !== void 0 ? layoutSectionStart : (0, _createAnchorDecorationWidgets.clampAnchorPosIntoCell)(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
265
278
  var decorations = [];
266
279
  if (hoisted) {
267
280
  decorations.push(hoisted.marker);
@@ -8,6 +8,7 @@ exports.createNodeChangedDecorationWidget = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _view = require("@atlaskit/editor-prosemirror/view");
10
10
  var _fg = require("@atlaskit/platform-feature-flags/fg");
11
+ var _baseNodeName = require("../utils/baseNodeName");
11
12
  var _emptyTextBlocks = require("../utils/emptyTextBlocks");
12
13
  var _isEmptyParagraphSlice = require("../utils/isEmptyParagraphSlice");
13
14
  var _createAnchorDecorationWidgets = require("./createAnchorDecorationWidgets");
@@ -124,7 +125,7 @@ var createTableCellContentWidgets = function createTableCellContentWidgets(_ref)
124
125
  * that is not in the current document.
125
126
  */
126
127
  var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidget = function createNodeChangedDecorationWidget(_ref2) {
127
- var _$safeInsertPos$nodeB, _slice$content$firstC, _newDoc$firstChild, _slice$content$firstC2;
128
+ var _$safeInsertPos$nodeB, _slice$content$firstC, _newDoc$firstChild, _hoistedCodeBlockAnch, _slice$content$firstC2;
128
129
  var attributionKey = _ref2.attributionKey,
129
130
  change = _ref2.change,
130
131
  doc = _ref2.doc,
@@ -280,6 +281,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
280
281
  // Match the rendering predicate above: an empty paragraph has no widget to tag, while whitespace
281
282
  // text in a rendered widget remains eligible.
282
283
  var canTagWidget = showContributorTags && !shouldSkipDeletedEmptyParagraphDecoration;
284
+ var contributorTagAnchorName;
283
285
  var decorations = [];
284
286
  var replacementNode = newDoc.nodeAt(change.fromB);
285
287
  var firstReplacedNode = slice.content.firstChild;
@@ -380,6 +382,14 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
380
382
  var $sourcePos = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
381
383
  var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined, isInserted, colorScheme);
382
384
  if (nodeView) {
385
+ if (canTagWidget && contributorTagAnchorName === undefined && (0, _baseNodeName.resolveBaseNodeName)(node.type.name) === 'layoutColumn' && nodeView instanceof HTMLElement && (0, _fg.fg)('confluence_ncs_step_diffing_version_history')) {
386
+ // The deleted column is rendered inside this widget; anchor to its box.
387
+ contributorTagAnchorName = (0, _decorationKeys.buildAnchorDecorationKey)({
388
+ diffId: diffId,
389
+ anchorType: _decorationKeys.AnchorTypeKey.tag
390
+ });
391
+ nodeView.style.setProperty('anchor-name', "--".concat(contributorTagAnchorName));
392
+ }
383
393
  if (node.isInline) {
384
394
  var wrapper = (0, _wrapBlockNodeView.createContentWrapper)(colorScheme, isActive, isInserted, reveal);
385
395
  wrapper.append(nodeView);
@@ -427,7 +437,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
427
437
  if (hoistedCodeBlockAnchor) {
428
438
  decorations.push(hoistedCodeBlockAnchor.marker);
429
439
  }
430
- var contributorTagAnchorName = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName;
440
+ contributorTagAnchorName = (_hoistedCodeBlockAnch = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName) !== null && _hoistedCodeBlockAnch !== void 0 ? _hoistedCodeBlockAnch : contributorTagAnchorName;
431
441
  if (!isInserted && deletedColumns !== null && deletedColumns !== void 0 && deletedColumns.length) {
432
442
  var table = dom.querySelector('table');
433
443
  var firstRow = table === null || table === void 0 ? void 0 : table.rows[0];
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.extractContributorTags = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
- var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
10
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
10
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
11
  var _fg = require("@atlaskit/platform-feature-flags/fg");
12
+ var _baseNodeName = require("../utils/baseNodeName");
13
13
  var _decorationKeys = require("./decorationKeys");
14
14
  var _excluded = ["connectedToKey"];
15
15
  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; }
@@ -75,12 +75,27 @@ var byLeadingPosition = function byLeadingPosition(a, b) {
75
75
  return a.decoration.from - b.decoration.from || ((_a$decoration$spec$si = a.decoration.spec.side) !== null && _a$decoration$spec$si !== void 0 ? _a$decoration$spec$si : 0) - ((_b$decoration$spec$si = b.decoration.spec.side) !== null && _b$decoration$spec$si !== void 0 ? _b$decoration$spec$si : 0) || a.decoration.to - a.decoration.from - (b.decoration.to - b.decoration.from);
76
76
  };
77
77
 
78
- /** The targets a navigation range wholly covers, leader first. */
79
- var containedBy = function containedBy(targets, _ref2) {
80
- var from = _ref2.from,
81
- to = _ref2.to;
82
- return targets.filter(function (_ref3) {
78
+ /** Select the first layout column only when the inline layout range starts immediately before it. */
79
+ var navigationLeader = function navigationLeader(members) {
80
+ var ordered = (0, _toConsumableArray2.default)(members).sort(byLeadingPosition);
81
+ var layoutColumn = (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? ordered.find(function (_ref2) {
82
+ var _decoration$spec$node;
83
+ var decoration = _ref2.decoration;
84
+ return decoration.spec.decorationType === 'block' && (0, _baseNodeName.resolveBaseNodeName)((_decoration$spec$node = decoration.spec.nodeName) !== null && _decoration$spec$node !== void 0 ? _decoration$spec$node : '') === 'layoutColumn';
85
+ }) : undefined;
86
+ var startsWholeLayout = layoutColumn !== undefined && members.some(function (_ref3) {
83
87
  var decoration = _ref3.decoration;
88
+ return decoration.spec.decorationType === 'inline' && decoration.from === layoutColumn.decoration.from - 1;
89
+ });
90
+ return startsWholeLayout ? layoutColumn : ordered[0];
91
+ };
92
+
93
+ /** The targets a navigation range wholly covers, leader first. */
94
+ var containedBy = function containedBy(targets, _ref4) {
95
+ var from = _ref4.from,
96
+ to = _ref4.to;
97
+ return targets.filter(function (_ref5) {
98
+ var decoration = _ref5.decoration;
84
99
  return from <= decoration.from && decoration.to <= to;
85
100
  }).sort(byLeadingPosition);
86
101
  };
@@ -154,16 +169,16 @@ var extractContributorTags = exports.extractContributorTags = function extractCo
154
169
  } finally {
155
170
  _iterator.f();
156
171
  }
157
- var inlineTargets = targets.filter(function (_ref4) {
158
- var decoration = _ref4.decoration;
172
+ var inlineTargets = targets.filter(function (_ref6) {
173
+ var decoration = _ref6.decoration;
159
174
  return decoration.spec.decorationType === 'inline';
160
175
  });
161
- var blockTargets = targets.filter(function (_ref5) {
162
- var decoration = _ref5.decoration;
176
+ var blockTargets = targets.filter(function (_ref7) {
177
+ var decoration = _ref7.decoration;
163
178
  return decoration.spec.decorationType === 'block';
164
179
  });
165
- var widgetTargets = targets.filter(function (_ref6) {
166
- var decoration = _ref6.decoration;
180
+ var widgetTargets = targets.filter(function (_ref8) {
181
+ var decoration = _ref8.decoration;
167
182
  return decoration.spec.decorationType === 'widget';
168
183
  });
169
184
  var linkedDiffIds = new Map();
@@ -191,8 +206,8 @@ var extractContributorTags = exports.extractContributorTags = function extractCo
191
206
  }
192
207
 
193
208
  // A block outranks both other kinds, so it is tried first.
194
- var block = blockTargets.find(function (_ref7) {
195
- var decoration = _ref7.decoration;
209
+ var block = blockTargets.find(function (_ref9) {
210
+ var decoration = _ref9.decoration;
196
211
  return isSameBlockChange(target.decoration, decoration);
197
212
  });
198
213
  if (block) {
@@ -201,8 +216,8 @@ var extractContributorTags = exports.extractContributorTags = function extractCo
201
216
  }
202
217
  if (decorationType === 'inline') {
203
218
  // The deleted half renders in front of this one, so that half captions the change.
204
- var leadingWidget = widgetTargets.find(function (_ref8) {
205
- var decoration = _ref8.decoration;
219
+ var leadingWidget = widgetTargets.find(function (_ref0) {
220
+ var decoration = _ref0.decoration;
206
221
  return leadsReplacement(decoration) && isSameChange(decoration, target.decoration);
207
222
  });
208
223
  if (leadingWidget) {
@@ -215,8 +230,8 @@ var extractContributorTags = exports.extractContributorTags = function extractCo
215
230
  if (leadsReplacement(target.decoration)) {
216
231
  return 0; // continue
217
232
  }
218
- var host = inlineTargets.find(function (_ref9) {
219
- var decoration = _ref9.decoration;
233
+ var host = inlineTargets.find(function (_ref1) {
234
+ var decoration = _ref1.decoration;
220
235
  return isSameChange(target.decoration, decoration);
221
236
  });
222
237
  if (host) {
@@ -320,10 +335,10 @@ var extractContributorTags = exports.extractContributorTags = function extractCo
320
335
  try {
321
336
  var _loop2 = function _loop2() {
322
337
  var members = _step6.value;
323
- var _sort = (0, _toConsumableArray2.default)(members).sort(byLeadingPosition),
324
- _sort2 = (0, _toArray2.default)(_sort),
325
- leader = _sort2[0],
326
- trailing = _arrayLikeToArray(_sort2).slice(1);
338
+ var leader = navigationLeader(members);
339
+ var trailing = members.filter(function (target) {
340
+ return target !== leader;
341
+ });
327
342
  trailing.forEach(function (target) {
328
343
  return fold(leader, target);
329
344
  });
@@ -12,6 +12,7 @@ var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
12
12
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
13
13
  var _fg = require("@atlaskit/platform-feature-flags/fg");
14
14
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
15
+ var _baseNodeName = require("../../utils/baseNodeName");
15
16
  var _createInlineChangedDecoration = require("../createInlineChangedDecoration");
16
17
  var _revealStyles = require("../revealStyles");
17
18
  var _getAttrChangeRanges = require("./getAttrChangeRanges");
@@ -353,6 +354,15 @@ var createBlockNodeContentWrapper = function createBlockNodeContentWrapper(_ref9
353
354
  // should not also get the inline content style (borderBottom underline) on their container.
354
355
  var shouldSkipContentStyle = isInserted && nodeStyle !== undefined;
355
356
  var contentStyle = shouldSkipContentStyle ? '' : (0, _wrapBlockNodeViewStyles.getChangedContentStyle)(colorScheme, isActive, isInserted, hideAddedDiffsUnderline);
357
+ var isEmptyDeletedLayoutColumn = !isInserted && (0, _baseNodeName.resolveBaseNodeName)(targetNode.type.name) === 'layoutColumn' && targetNode.textContent.length === 0 && (0, _fg.fg)('confluence_ncs_step_diffing_version_history');
358
+ if (isEmptyDeletedLayoutColumn && nodeView instanceof HTMLElement) {
359
+ var _nodeView$querySelect;
360
+ // Give an empty deleted column height so its diff box doesn't collapse
361
+ var placeholderTarget = (_nodeView$querySelect = nodeView.querySelector('[data-layout-content]')) !== null && _nodeView$querySelect !== void 0 ? _nodeView$querySelect : nodeView;
362
+ appendStyleToElement(placeholderTarget, (0, _lazyNodeView.convertToInlineCss)({
363
+ minHeight: "var(--ds-space-300, 24px)"
364
+ }));
365
+ }
356
366
 
357
367
  // A `breakout` node renders wider than the editor column while the wrapper divs
358
368
  // stay at column width, so paint the outline on the node element that spans that width.
@@ -15,7 +15,7 @@ var _baseNodeName = require("./baseNodeName");
15
15
  *
16
16
  * Base names only — match with the predicates below, never against `type.name` directly.
17
17
  */
18
- var TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
18
+ var TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'layoutColumn', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
19
19
 
20
20
  /**
21
21
  * Whether this node hosts a contributor tag of its own. Navigation grouping does not consult this:
@@ -1,6 +1,7 @@
1
1
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
2
  import { fg } from '@atlaskit/platform-feature-flags/fg';
3
3
  import { ContributorTagController } from '../../ui/ContributorTag/contributorTagController';
4
+ import { resolveBaseNodeName } from '../utils/baseNodeName';
4
5
  import { buildCharsByOffset, isWhitespaceChar } from '../utils/charsByOffset';
5
6
  import { clampAnchorPosIntoCell, createAnchorNameSpan } from './createAnchorDecorationWidgets';
6
7
  import { AnchorTypeKey, buildAnchorDecorationKey, buildAnchorDecorationSpec, buildContributorTagDecorationSpec } from './decorationKeys';
@@ -207,6 +208,16 @@ export const resolveHoistedCodeBlockAnchor = (doc, pos, diffId) => {
207
208
  };
208
209
  };
209
210
 
211
+ /** Find the position before a layout for a tag anchored to one of its columns. */
212
+ const resolveLayoutSectionStart = (doc, pos) => {
213
+ var _doc$nodeAt$type$name, _doc$nodeAt;
214
+ if (resolveBaseNodeName((_doc$nodeAt$type$name = (_doc$nodeAt = doc.nodeAt(pos)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type.name) !== null && _doc$nodeAt$type$name !== void 0 ? _doc$nodeAt$type$name : '') !== 'layoutColumn') {
215
+ return undefined;
216
+ }
217
+ const $pos = doc.resolve(pos);
218
+ return resolveBaseNodeName($pos.parent.type.name) === 'layoutSection' ? $pos.before($pos.depth) : undefined;
219
+ };
220
+
210
221
  /**
211
222
  * The contributor tag widget for one diff range, placed on the first visible character the range
212
223
  * highlights — or, with `anchorAtRangeStart`, at `from` itself. A host inside a code block is
@@ -227,7 +238,7 @@ export const createContributorTagWidget = ({
227
238
  diffId,
228
239
  mountContext
229
240
  }) => {
230
- var _hoisted$codeBlockSta, _ref2, _hoisted$anchorName;
241
+ var _ref2, _hoisted$anchorName, _hoisted$codeBlockSta;
231
242
  if (!isContributorTagWidgetEnabled()) {
232
243
  return undefined;
233
244
  }
@@ -239,8 +250,6 @@ export const createContributorTagWidget = ({
239
250
  // A change inside a code block is hoisted out of it, anchored to its own marker; anything else
240
251
  // keeps its own anchor.
241
252
  const hoisted = resolveHoistedCodeBlockAnchor(doc, anchorPos, diffId);
242
- // Keep the host out of the table row's grid (EDITOR-8442).
243
- const hostPos = clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
244
253
 
245
254
  // Inline diffs pass no anchorName. Give them their own point anchor instead of the
246
255
  // `position: relative` fallback, which drifts left once the range wraps a line (EDITOR-9286).
@@ -250,6 +259,10 @@ export const createContributorTagWidget = ({
250
259
  });
251
260
  const effectiveAnchorName = (_ref2 = (_hoisted$anchorName = hoisted === null || hoisted === void 0 ? void 0 : hoisted.anchorName) !== null && _hoisted$anchorName !== void 0 ? _hoisted$anchorName : anchorName) !== null && _ref2 !== void 0 ? _ref2 : ownAnchorName;
252
261
  const tagAnchorName = effectiveAnchorName && supportsAnchorPositioning() ? effectiveAnchorName : undefined;
262
+ const layoutSectionStart = tagAnchorName ? resolveLayoutSectionStart(doc, anchorPos) : undefined;
263
+ // Keep the host out of the table row's grid (EDITOR-8442). Layout-column tags are hoisted before
264
+ // their layout so the advanced layout widget-flattening rule cannot put them behind nearby text.
265
+ const hostPos = layoutSectionStart !== null && layoutSectionStart !== void 0 ? layoutSectionStart : clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
253
266
  const decorations = [];
254
267
  if (hoisted) {
255
268
  decorations.push(hoisted.marker);
@@ -1,5 +1,6 @@
1
1
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
2
  import { fg } from '@atlaskit/platform-feature-flags/fg';
3
+ import { resolveBaseNodeName } from '../utils/baseNodeName';
3
4
  import { countEmptyTextBlockOnlySlice } from '../utils/emptyTextBlocks';
4
5
  import { isEmptyParagraphSlice } from '../utils/isEmptyParagraphSlice';
5
6
  import { clampAnchorPosIntoCell, createAnchorNameSpan, createLeftAnchorWidget } from './createAnchorDecorationWidgets';
@@ -138,7 +139,7 @@ export const createNodeChangedDecorationWidget = ({
138
139
  tagMountContext,
139
140
  deletedColumns
140
141
  }) => {
141
- var _$safeInsertPos$nodeB, _slice$content$firstC, _newDoc$firstChild, _slice$content$firstC2;
142
+ var _$safeInsertPos$nodeB, _slice$content$firstC, _newDoc$firstChild, _hoistedCodeBlockAnch, _slice$content$firstC2;
142
143
  const slice = doc.slice(change.fromA, change.toA);
143
144
  const shouldSkipDeletedEmptyParagraphDecoration = !isInserted && isEmptyParagraphSlice(slice);
144
145
  // How many blank lines the deletion took, when it took nothing else. Blank means an empty
@@ -272,6 +273,7 @@ export const createNodeChangedDecorationWidget = ({
272
273
  // Match the rendering predicate above: an empty paragraph has no widget to tag, while whitespace
273
274
  // text in a rendered widget remains eligible.
274
275
  const canTagWidget = showContributorTags && !shouldSkipDeletedEmptyParagraphDecoration;
276
+ let contributorTagAnchorName;
275
277
  const decorations = [];
276
278
  const replacementNode = newDoc.nodeAt(change.fromB);
277
279
  const firstReplacedNode = slice.content.firstChild;
@@ -366,6 +368,14 @@ export const createNodeChangedDecorationWidget = ({
366
368
  const $sourcePos = fg('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
367
369
  const nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined, isInserted, colorScheme);
368
370
  if (nodeView) {
371
+ if (canTagWidget && contributorTagAnchorName === undefined && resolveBaseNodeName(node.type.name) === 'layoutColumn' && nodeView instanceof HTMLElement && fg('confluence_ncs_step_diffing_version_history')) {
372
+ // The deleted column is rendered inside this widget; anchor to its box.
373
+ contributorTagAnchorName = buildAnchorDecorationKey({
374
+ diffId,
375
+ anchorType: AnchorTypeKey.tag
376
+ });
377
+ nodeView.style.setProperty('anchor-name', `--${contributorTagAnchorName}`);
378
+ }
369
379
  if (node.isInline) {
370
380
  const wrapper = createContentWrapper(colorScheme, isActive, isInserted, reveal);
371
381
  wrapper.append(nodeView);
@@ -413,7 +423,7 @@ export const createNodeChangedDecorationWidget = ({
413
423
  if (hoistedCodeBlockAnchor) {
414
424
  decorations.push(hoistedCodeBlockAnchor.marker);
415
425
  }
416
- let contributorTagAnchorName = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName;
426
+ contributorTagAnchorName = (_hoistedCodeBlockAnch = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName) !== null && _hoistedCodeBlockAnch !== void 0 ? _hoistedCodeBlockAnch : contributorTagAnchorName;
417
427
  if (!isInserted && deletedColumns !== null && deletedColumns !== void 0 && deletedColumns.length) {
418
428
  const table = dom.querySelector('table');
419
429
  const firstRow = table === null || table === void 0 ? void 0 : table.rows[0];
@@ -1,4 +1,5 @@
1
1
  import { fg } from '@atlaskit/platform-feature-flags/fg';
2
+ import { resolveBaseNodeName } from '../utils/baseNodeName';
2
3
  import { isDiffDecoration, isDiffDecorationSpec } from './decorationKeys';
3
4
 
4
5
  /**
@@ -50,6 +51,21 @@ const byLeadingPosition = (a, b) => {
50
51
  return a.decoration.from - b.decoration.from || ((_a$decoration$spec$si = a.decoration.spec.side) !== null && _a$decoration$spec$si !== void 0 ? _a$decoration$spec$si : 0) - ((_b$decoration$spec$si = b.decoration.spec.side) !== null && _b$decoration$spec$si !== void 0 ? _b$decoration$spec$si : 0) || a.decoration.to - a.decoration.from - (b.decoration.to - b.decoration.from);
51
52
  };
52
53
 
54
+ /** Select the first layout column only when the inline layout range starts immediately before it. */
55
+ const navigationLeader = members => {
56
+ const ordered = [...members].sort(byLeadingPosition);
57
+ const layoutColumn = fg('confluence_ncs_step_diffing_version_history') ? ordered.find(({
58
+ decoration
59
+ }) => {
60
+ var _decoration$spec$node;
61
+ return decoration.spec.decorationType === 'block' && resolveBaseNodeName((_decoration$spec$node = decoration.spec.nodeName) !== null && _decoration$spec$node !== void 0 ? _decoration$spec$node : '') === 'layoutColumn';
62
+ }) : undefined;
63
+ const startsWholeLayout = layoutColumn !== undefined && members.some(({
64
+ decoration
65
+ }) => decoration.spec.decorationType === 'inline' && decoration.from === layoutColumn.decoration.from - 1);
66
+ return startsWholeLayout ? layoutColumn : ordered[0];
67
+ };
68
+
53
69
  /** The targets a navigation range wholly covers, leader first. */
54
70
  const containedBy = (targets, {
55
71
  from,
@@ -224,7 +240,8 @@ export const extractContributorTags = (decorations, contributors, activeIndexPos
224
240
  byStopAndContributor.set(key, [...((_byStopAndContributor = byStopAndContributor.get(key)) !== null && _byStopAndContributor !== void 0 ? _byStopAndContributor : []), target]);
225
241
  }
226
242
  for (const members of byStopAndContributor.values()) {
227
- const [leader, ...trailing] = [...members].sort(byLeadingPosition);
243
+ const leader = navigationLeader(members);
244
+ const trailing = members.filter(target => target !== leader);
228
245
  trailing.forEach(target => fold(leader, target));
229
246
  }
230
247
  }
@@ -4,6 +4,7 @@ import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-uti
4
4
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
5
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
6
6
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
+ import { resolveBaseNodeName } from '../../utils/baseNodeName';
7
8
  import { getAtomicInlineChangedAttrs } from '../createInlineChangedDecoration';
8
9
  import { applyRevealToElement } from '../revealStyles';
9
10
  import { isInlineAttrChangeNodeName } from './getAttrChangeRanges';
@@ -341,6 +342,15 @@ const createBlockNodeContentWrapper = ({
341
342
  // should not also get the inline content style (borderBottom underline) on their container.
342
343
  const shouldSkipContentStyle = isInserted && nodeStyle !== undefined;
343
344
  const contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, hideAddedDiffsUnderline);
345
+ const isEmptyDeletedLayoutColumn = !isInserted && resolveBaseNodeName(targetNode.type.name) === 'layoutColumn' && targetNode.textContent.length === 0 && fg('confluence_ncs_step_diffing_version_history');
346
+ if (isEmptyDeletedLayoutColumn && nodeView instanceof HTMLElement) {
347
+ var _nodeView$querySelect;
348
+ // Give an empty deleted column height so its diff box doesn't collapse
349
+ const placeholderTarget = (_nodeView$querySelect = nodeView.querySelector('[data-layout-content]')) !== null && _nodeView$querySelect !== void 0 ? _nodeView$querySelect : nodeView;
350
+ appendStyleToElement(placeholderTarget, convertToInlineCss({
351
+ minHeight: "var(--ds-space-300, 24px)"
352
+ }));
353
+ }
344
354
 
345
355
  // A `breakout` node renders wider than the editor column while the wrapper divs
346
356
  // stay at column width, so paint the outline on the node element that spans that width.
@@ -10,7 +10,7 @@ import { resolveBaseNodeName } from './baseNodeName';
10
10
  *
11
11
  * Base names only — match with the predicates below, never against `type.name` directly.
12
12
  */
13
- const TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
13
+ const TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'layoutColumn', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
14
14
 
15
15
  /**
16
16
  * Whether this node hosts a contributor tag of its own. Navigation grouping does not consult this:
@@ -4,6 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
6
6
  import { ContributorTagController } from '../../ui/ContributorTag/contributorTagController';
7
+ import { resolveBaseNodeName } from '../utils/baseNodeName';
7
8
  import { buildCharsByOffset, isWhitespaceChar } from '../utils/charsByOffset';
8
9
  import { clampAnchorPosIntoCell, createAnchorNameSpan } from './createAnchorDecorationWidgets';
9
10
  import { AnchorTypeKey, buildAnchorDecorationKey, buildAnchorDecorationSpec, buildContributorTagDecorationSpec } from './decorationKeys';
@@ -213,6 +214,16 @@ export var resolveHoistedCodeBlockAnchor = function resolveHoistedCodeBlockAncho
213
214
  };
214
215
  };
215
216
 
217
+ /** Find the position before a layout for a tag anchored to one of its columns. */
218
+ var resolveLayoutSectionStart = function resolveLayoutSectionStart(doc, pos) {
219
+ var _doc$nodeAt$type$name, _doc$nodeAt;
220
+ if (resolveBaseNodeName((_doc$nodeAt$type$name = (_doc$nodeAt = doc.nodeAt(pos)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type.name) !== null && _doc$nodeAt$type$name !== void 0 ? _doc$nodeAt$type$name : '') !== 'layoutColumn') {
221
+ return undefined;
222
+ }
223
+ var $pos = doc.resolve(pos);
224
+ return resolveBaseNodeName($pos.parent.type.name) === 'layoutSection' ? $pos.before($pos.depth) : undefined;
225
+ };
226
+
216
227
  /**
217
228
  * The contributor tag widget for one diff range, placed on the first visible character the range
218
229
  * highlights — or, with `anchorAtRangeStart`, at `from` itself. A host inside a code block is
@@ -225,7 +236,7 @@ export var resolveHoistedCodeBlockAnchor = function resolveHoistedCodeBlockAncho
225
236
  * element ProseMirror drew it into — see `mountContributorTag`.
226
237
  */
227
238
  export var createContributorTagWidget = function createContributorTagWidget(_ref4) {
228
- var _hoisted$codeBlockSta, _ref5, _hoisted$anchorName;
239
+ var _ref5, _hoisted$anchorName, _hoisted$codeBlockSta;
229
240
  var _ref4$anchorAtRangeSt = _ref4.anchorAtRangeStart,
230
241
  anchorAtRangeStart = _ref4$anchorAtRangeSt === void 0 ? false : _ref4$anchorAtRangeSt,
231
242
  anchorName = _ref4.anchorName,
@@ -245,8 +256,6 @@ export var createContributorTagWidget = function createContributorTagWidget(_ref
245
256
  // A change inside a code block is hoisted out of it, anchored to its own marker; anything else
246
257
  // keeps its own anchor.
247
258
  var hoisted = resolveHoistedCodeBlockAnchor(doc, anchorPos, diffId);
248
- // Keep the host out of the table row's grid (EDITOR-8442).
249
- var hostPos = clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
250
259
 
251
260
  // Inline diffs pass no anchorName. Give them their own point anchor instead of the
252
261
  // `position: relative` fallback, which drifts left once the range wraps a line (EDITOR-9286).
@@ -256,6 +265,10 @@ export var createContributorTagWidget = function createContributorTagWidget(_ref
256
265
  });
257
266
  var effectiveAnchorName = (_ref5 = (_hoisted$anchorName = hoisted === null || hoisted === void 0 ? void 0 : hoisted.anchorName) !== null && _hoisted$anchorName !== void 0 ? _hoisted$anchorName : anchorName) !== null && _ref5 !== void 0 ? _ref5 : ownAnchorName;
258
267
  var tagAnchorName = effectiveAnchorName && supportsAnchorPositioning() ? effectiveAnchorName : undefined;
268
+ var layoutSectionStart = tagAnchorName ? resolveLayoutSectionStart(doc, anchorPos) : undefined;
269
+ // Keep the host out of the table row's grid (EDITOR-8442). Layout-column tags are hoisted before
270
+ // their layout so the advanced layout widget-flattening rule cannot put them behind nearby text.
271
+ var hostPos = layoutSectionStart !== null && layoutSectionStart !== void 0 ? layoutSectionStart : clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
259
272
  var decorations = [];
260
273
  if (hoisted) {
261
274
  decorations.push(hoisted.marker);
@@ -3,6 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
3
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; }
4
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
6
+ import { resolveBaseNodeName } from '../utils/baseNodeName';
6
7
  import { countEmptyTextBlockOnlySlice } from '../utils/emptyTextBlocks';
7
8
  import { isEmptyParagraphSlice } from '../utils/isEmptyParagraphSlice';
8
9
  import { clampAnchorPosIntoCell, createAnchorNameSpan, createLeftAnchorWidget } from './createAnchorDecorationWidgets';
@@ -118,7 +119,7 @@ var createTableCellContentWidgets = function createTableCellContentWidgets(_ref)
118
119
  * that is not in the current document.
119
120
  */
120
121
  export var createNodeChangedDecorationWidget = function createNodeChangedDecorationWidget(_ref2) {
121
- var _$safeInsertPos$nodeB, _slice$content$firstC, _newDoc$firstChild, _slice$content$firstC2;
122
+ var _$safeInsertPos$nodeB, _slice$content$firstC, _newDoc$firstChild, _hoistedCodeBlockAnch, _slice$content$firstC2;
122
123
  var attributionKey = _ref2.attributionKey,
123
124
  change = _ref2.change,
124
125
  doc = _ref2.doc,
@@ -274,6 +275,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
274
275
  // Match the rendering predicate above: an empty paragraph has no widget to tag, while whitespace
275
276
  // text in a rendered widget remains eligible.
276
277
  var canTagWidget = showContributorTags && !shouldSkipDeletedEmptyParagraphDecoration;
278
+ var contributorTagAnchorName;
277
279
  var decorations = [];
278
280
  var replacementNode = newDoc.nodeAt(change.fromB);
279
281
  var firstReplacedNode = slice.content.firstChild;
@@ -374,6 +376,14 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
374
376
  var $sourcePos = fg('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
375
377
  var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined, isInserted, colorScheme);
376
378
  if (nodeView) {
379
+ if (canTagWidget && contributorTagAnchorName === undefined && resolveBaseNodeName(node.type.name) === 'layoutColumn' && nodeView instanceof HTMLElement && fg('confluence_ncs_step_diffing_version_history')) {
380
+ // The deleted column is rendered inside this widget; anchor to its box.
381
+ contributorTagAnchorName = buildAnchorDecorationKey({
382
+ diffId: diffId,
383
+ anchorType: AnchorTypeKey.tag
384
+ });
385
+ nodeView.style.setProperty('anchor-name', "--".concat(contributorTagAnchorName));
386
+ }
377
387
  if (node.isInline) {
378
388
  var wrapper = createContentWrapper(colorScheme, isActive, isInserted, reveal);
379
389
  wrapper.append(nodeView);
@@ -421,7 +431,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
421
431
  if (hoistedCodeBlockAnchor) {
422
432
  decorations.push(hoistedCodeBlockAnchor.marker);
423
433
  }
424
- var contributorTagAnchorName = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName;
434
+ contributorTagAnchorName = (_hoistedCodeBlockAnch = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName) !== null && _hoistedCodeBlockAnch !== void 0 ? _hoistedCodeBlockAnch : contributorTagAnchorName;
425
435
  if (!isInserted && deletedColumns !== null && deletedColumns !== void 0 && deletedColumns.length) {
426
436
  var table = dom.querySelector('table');
427
437
  var firstRow = table === null || table === void 0 ? void 0 : table.rows[0];
@@ -1,5 +1,4 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import _toArray from "@babel/runtime/helpers/toArray";
3
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
4
3
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
4
  var _excluded = ["connectedToKey"];
@@ -9,6 +8,7 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
9
8
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
9
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
11
10
  import { fg } from '@atlaskit/platform-feature-flags/fg';
11
+ import { resolveBaseNodeName } from '../utils/baseNodeName';
12
12
  import { isDiffDecoration, isDiffDecorationSpec } from './decorationKeys';
13
13
 
14
14
  /**
@@ -69,12 +69,27 @@ var byLeadingPosition = function byLeadingPosition(a, b) {
69
69
  return a.decoration.from - b.decoration.from || ((_a$decoration$spec$si = a.decoration.spec.side) !== null && _a$decoration$spec$si !== void 0 ? _a$decoration$spec$si : 0) - ((_b$decoration$spec$si = b.decoration.spec.side) !== null && _b$decoration$spec$si !== void 0 ? _b$decoration$spec$si : 0) || a.decoration.to - a.decoration.from - (b.decoration.to - b.decoration.from);
70
70
  };
71
71
 
72
- /** The targets a navigation range wholly covers, leader first. */
73
- var containedBy = function containedBy(targets, _ref2) {
74
- var from = _ref2.from,
75
- to = _ref2.to;
76
- return targets.filter(function (_ref3) {
72
+ /** Select the first layout column only when the inline layout range starts immediately before it. */
73
+ var navigationLeader = function navigationLeader(members) {
74
+ var ordered = _toConsumableArray(members).sort(byLeadingPosition);
75
+ var layoutColumn = fg('confluence_ncs_step_diffing_version_history') ? ordered.find(function (_ref2) {
76
+ var _decoration$spec$node;
77
+ var decoration = _ref2.decoration;
78
+ return decoration.spec.decorationType === 'block' && resolveBaseNodeName((_decoration$spec$node = decoration.spec.nodeName) !== null && _decoration$spec$node !== void 0 ? _decoration$spec$node : '') === 'layoutColumn';
79
+ }) : undefined;
80
+ var startsWholeLayout = layoutColumn !== undefined && members.some(function (_ref3) {
77
81
  var decoration = _ref3.decoration;
82
+ return decoration.spec.decorationType === 'inline' && decoration.from === layoutColumn.decoration.from - 1;
83
+ });
84
+ return startsWholeLayout ? layoutColumn : ordered[0];
85
+ };
86
+
87
+ /** The targets a navigation range wholly covers, leader first. */
88
+ var containedBy = function containedBy(targets, _ref4) {
89
+ var from = _ref4.from,
90
+ to = _ref4.to;
91
+ return targets.filter(function (_ref5) {
92
+ var decoration = _ref5.decoration;
78
93
  return from <= decoration.from && decoration.to <= to;
79
94
  }).sort(byLeadingPosition);
80
95
  };
@@ -148,16 +163,16 @@ export var extractContributorTags = function extractContributorTags(decorations,
148
163
  } finally {
149
164
  _iterator.f();
150
165
  }
151
- var inlineTargets = targets.filter(function (_ref4) {
152
- var decoration = _ref4.decoration;
166
+ var inlineTargets = targets.filter(function (_ref6) {
167
+ var decoration = _ref6.decoration;
153
168
  return decoration.spec.decorationType === 'inline';
154
169
  });
155
- var blockTargets = targets.filter(function (_ref5) {
156
- var decoration = _ref5.decoration;
170
+ var blockTargets = targets.filter(function (_ref7) {
171
+ var decoration = _ref7.decoration;
157
172
  return decoration.spec.decorationType === 'block';
158
173
  });
159
- var widgetTargets = targets.filter(function (_ref6) {
160
- var decoration = _ref6.decoration;
174
+ var widgetTargets = targets.filter(function (_ref8) {
175
+ var decoration = _ref8.decoration;
161
176
  return decoration.spec.decorationType === 'widget';
162
177
  });
163
178
  var linkedDiffIds = new Map();
@@ -185,8 +200,8 @@ export var extractContributorTags = function extractContributorTags(decorations,
185
200
  }
186
201
 
187
202
  // A block outranks both other kinds, so it is tried first.
188
- var block = blockTargets.find(function (_ref7) {
189
- var decoration = _ref7.decoration;
203
+ var block = blockTargets.find(function (_ref9) {
204
+ var decoration = _ref9.decoration;
190
205
  return isSameBlockChange(target.decoration, decoration);
191
206
  });
192
207
  if (block) {
@@ -195,8 +210,8 @@ export var extractContributorTags = function extractContributorTags(decorations,
195
210
  }
196
211
  if (decorationType === 'inline') {
197
212
  // The deleted half renders in front of this one, so that half captions the change.
198
- var leadingWidget = widgetTargets.find(function (_ref8) {
199
- var decoration = _ref8.decoration;
213
+ var leadingWidget = widgetTargets.find(function (_ref0) {
214
+ var decoration = _ref0.decoration;
200
215
  return leadsReplacement(decoration) && isSameChange(decoration, target.decoration);
201
216
  });
202
217
  if (leadingWidget) {
@@ -209,8 +224,8 @@ export var extractContributorTags = function extractContributorTags(decorations,
209
224
  if (leadsReplacement(target.decoration)) {
210
225
  return 0; // continue
211
226
  }
212
- var host = inlineTargets.find(function (_ref9) {
213
- var decoration = _ref9.decoration;
227
+ var host = inlineTargets.find(function (_ref1) {
228
+ var decoration = _ref1.decoration;
214
229
  return isSameChange(target.decoration, decoration);
215
230
  });
216
231
  if (host) {
@@ -314,10 +329,10 @@ export var extractContributorTags = function extractContributorTags(decorations,
314
329
  try {
315
330
  var _loop2 = function _loop2() {
316
331
  var members = _step6.value;
317
- var _sort = _toConsumableArray(members).sort(byLeadingPosition),
318
- _sort2 = _toArray(_sort),
319
- leader = _sort2[0],
320
- trailing = _arrayLikeToArray(_sort2).slice(1);
332
+ var leader = navigationLeader(members);
333
+ var trailing = members.filter(function (target) {
334
+ return target !== leader;
335
+ });
321
336
  trailing.forEach(function (target) {
322
337
  return fold(leader, target);
323
338
  });
@@ -5,6 +5,7 @@ import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-uti
5
5
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
6
6
  import { fg } from '@atlaskit/platform-feature-flags/fg';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
+ import { resolveBaseNodeName } from '../../utils/baseNodeName';
8
9
  import { getAtomicInlineChangedAttrs } from '../createInlineChangedDecoration';
9
10
  import { applyRevealToElement } from '../revealStyles';
10
11
  import { isInlineAttrChangeNodeName } from './getAttrChangeRanges';
@@ -346,6 +347,15 @@ var createBlockNodeContentWrapper = function createBlockNodeContentWrapper(_ref9
346
347
  // should not also get the inline content style (borderBottom underline) on their container.
347
348
  var shouldSkipContentStyle = isInserted && nodeStyle !== undefined;
348
349
  var contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, hideAddedDiffsUnderline);
350
+ var isEmptyDeletedLayoutColumn = !isInserted && resolveBaseNodeName(targetNode.type.name) === 'layoutColumn' && targetNode.textContent.length === 0 && fg('confluence_ncs_step_diffing_version_history');
351
+ if (isEmptyDeletedLayoutColumn && nodeView instanceof HTMLElement) {
352
+ var _nodeView$querySelect;
353
+ // Give an empty deleted column height so its diff box doesn't collapse
354
+ var placeholderTarget = (_nodeView$querySelect = nodeView.querySelector('[data-layout-content]')) !== null && _nodeView$querySelect !== void 0 ? _nodeView$querySelect : nodeView;
355
+ appendStyleToElement(placeholderTarget, convertToInlineCss({
356
+ minHeight: "var(--ds-space-300, 24px)"
357
+ }));
358
+ }
349
359
 
350
360
  // A `breakout` node renders wider than the editor column while the wrapper divs
351
361
  // stay at column width, so paint the outline on the node element that spans that width.
@@ -10,7 +10,7 @@ import { resolveBaseNodeName } from './baseNodeName';
10
10
  *
11
11
  * Base names only — match with the predicates below, never against `type.name` directly.
12
12
  */
13
- var TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
13
+ var TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'layoutColumn', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
14
14
 
15
15
  /**
16
16
  * Whether this node hosts a contributor tag of its own. Navigation grouping does not consult this:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-show-diff",
3
- "version": "23.0.3",
3
+ "version": "24.0.1",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -29,18 +29,18 @@
29
29
  "@atlaskit/agent-color": "^1.0.0",
30
30
  "@atlaskit/avatar": "^30.0.0",
31
31
  "@atlaskit/custom-steps": "^1.1.0",
32
- "@atlaskit/editor-plugin-accessibility-utils": "^25.0.0",
33
- "@atlaskit/editor-plugin-analytics": "^25.0.0",
34
- "@atlaskit/editor-plugin-limited-mode": "^22.0.0",
35
- "@atlaskit/editor-plugin-user-intent": "^23.0.0",
32
+ "@atlaskit/editor-plugin-accessibility-utils": "^26.0.0",
33
+ "@atlaskit/editor-plugin-analytics": "^26.0.0",
34
+ "@atlaskit/editor-plugin-limited-mode": "^23.0.0",
35
+ "@atlaskit/editor-plugin-user-intent": "^24.0.0",
36
36
  "@atlaskit/editor-prosemirror": "^9.0.0",
37
37
  "@atlaskit/editor-shared-styles": "^4.3.0",
38
38
  "@atlaskit/editor-tables": "^3.2.0",
39
39
  "@atlaskit/platform-feature-experiments": "^0.3.0",
40
40
  "@atlaskit/platform-feature-flags": "^2.2.0",
41
41
  "@atlaskit/primitives": "^22.5.0",
42
- "@atlaskit/tmp-editor-statsig": "^227.0.0",
43
- "@atlaskit/tokens": "^20.3.0",
42
+ "@atlaskit/tmp-editor-statsig": "^228.0.0",
43
+ "@atlaskit/tokens": "^20.4.0",
44
44
  "@babel/runtime": "^7.0.0",
45
45
  "@compiled/react": "^1.0.2",
46
46
  "bind-event-listener": "^3.0.0",
@@ -53,7 +53,7 @@
53
53
  "@atlaskit/button": "^25.4.0",
54
54
  "@atlaskit/css": "^1.1.0",
55
55
  "@atlaskit/dropdown-menu": "^21.0.0",
56
- "@atlaskit/editor-core": "^235.0.0",
56
+ "@atlaskit/editor-core": "^236.0.0",
57
57
  "@atlaskit/editor-json-transformer": "^10.0.0",
58
58
  "@atlaskit/editor-plugins": "^16.2.0",
59
59
  "@atlaskit/form": "^18.2.0",
@@ -63,15 +63,15 @@
63
63
  "@atlaskit/util-data-test": "^19.1.0",
64
64
  "@atlassian/confluence-presets": "workspace:^",
65
65
  "@atlassian/content-reconciliation": "^0.1.3506",
66
- "@atlassian/editor-ai-injected-editors": "^39.0.0",
67
- "@atlassian/editor-plugin-ai": "^79.0.0",
66
+ "@atlassian/editor-ai-injected-editors": "^40.0.0",
67
+ "@atlassian/editor-plugin-ai": "^80.0.0",
68
68
  "@atlassian/structured-docs-types": "workspace:^",
69
69
  "react": "^19.2.0",
70
70
  "react-dom": "^19.2.0",
71
71
  "react-intl": "^7.0.0"
72
72
  },
73
73
  "peerDependencies": {
74
- "@atlaskit/editor-common": "^129.1.0",
74
+ "@atlaskit/editor-common": "^130.1.0",
75
75
  "react": "^18.2.0 || ^19.2.0",
76
76
  "react-dom": "^18.2.0 || ^19.2.0",
77
77
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"