@atlaskit/editor-plugin-show-diff 12.0.2 → 12.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 12.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`0a96aa66ed44f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0a96aa66ed44f) -
8
+ [ux] CCI-18372 Post Stream Review now renders deleted content below the added content at every
9
+ change level (gated behind `platform_editor_ai_smart_diff`), so reviewers read the new text first.
10
+
11
+ Deleted-content placement is split by change granularity, so consumers that want deleted content
12
+ after the new content everywhere must set both options (each defaults to rendering deleted content
13
+ first, and both require `diffType: 'smart'`):
14
+
15
+ ```ts
16
+ api?.showDiff?.commands?.showDiff({
17
+ originalDoc,
18
+ diffType: 'smart',
19
+ deletedDiffPlacement: 'bottom', // node/paragraph-level changes
20
+ inlineDeletedDiffPlacement: 'after', // inline/sentence-level changes
21
+ });
22
+ ```
23
+
24
+ `@atlaskit/editor-plugin-show-diff` also adds a `getDeletedWidgets` action (returning the
25
+ `DeletedDiffWidget` elements and positions), used by Post Stream Review to position the review
26
+ modal below relocated deleted content.
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies
31
+
32
+ ## 12.0.3
33
+
34
+ ### Patch Changes
35
+
36
+ - Updated dependencies
37
+
3
38
  ## 12.0.2
4
39
 
5
40
  ### Patch Changes
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.calculateDiffDecorations = void 0;
7
+ exports.isDeletedContentPlacedBelow = exports.calculateDiffDecorations = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
@@ -131,29 +131,52 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
131
131
  });
132
132
  return decorations;
133
133
  };
134
- var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3) {
135
- var state = _ref3.state,
136
- pluginState = _ref3.pluginState,
137
- nodeViewSerializer = _ref3.nodeViewSerializer,
138
- colorScheme = _ref3.colorScheme,
139
- intl = _ref3.intl,
140
- activeIndexPos = _ref3.activeIndexPos,
141
- api = _ref3.api,
142
- _ref3$isInverted = _ref3.isInverted,
143
- isInverted = _ref3$isInverted === void 0 ? false : _ref3$isInverted,
144
- _ref3$diffType = _ref3.diffType,
145
- diffType = _ref3$diffType === void 0 ? 'inline' : _ref3$diffType,
146
- _ref3$hideDeletedDiff = _ref3.hideDeletedDiffs,
147
- hideDeletedDiffs = _ref3$hideDeletedDiff === void 0 ? false : _ref3$hideDeletedDiff,
148
- _ref3$hideAddedDiffsU = _ref3.hideAddedDiffsUnderline,
149
- hideAddedDiffsUnderlineParam = _ref3$hideAddedDiffsU === void 0 ? false : _ref3$hideAddedDiffsU,
150
- _ref3$showIndicators = _ref3.showIndicators,
151
- showIndicators = _ref3$showIndicators === void 0 ? false : _ref3$showIndicators,
152
- smartThresholds = _ref3.smartThresholds,
153
- _ref3$deletedDiffPlac = _ref3.deletedDiffPlacement,
154
- deletedDiffPlacement = _ref3$deletedDiffPlac === void 0 ? 'top' : _ref3$deletedDiffPlac,
155
- _ref3$inlineDeletedDi = _ref3.inlineDeletedDiffPlacement,
156
- inlineDeletedDiffPlacement = _ref3$inlineDeletedDi === void 0 ? 'before' : _ref3$inlineDeletedDi;
134
+ /**
135
+ * Whether deleted content for `change` renders after the new content instead of before it.
136
+ *
137
+ * show-diff splits this across two options by change granularity, so the level decides which one
138
+ * applies:
139
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
140
+ * node level, so they are governed here too.
141
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
142
+ *
143
+ * Callers are responsible for the `smart` diffType and gate checks.
144
+ */
145
+ var isDeletedContentPlacedBelow = exports.isDeletedContentPlacedBelow = function isDeletedContentPlacedBelow(_ref3) {
146
+ var change = _ref3.change,
147
+ deletedDiffPlacement = _ref3.deletedDiffPlacement,
148
+ inlineDeletedDiffPlacement = _ref3.inlineDeletedDiffPlacement;
149
+ var level = (0, _helpers.smartChangeLevel)(change);
150
+ if (level === 'node' || level === 'paragraph') {
151
+ return deletedDiffPlacement === 'bottom';
152
+ }
153
+
154
+ // Inline-level (undefined) and sentence-level changes.
155
+ return inlineDeletedDiffPlacement === 'after';
156
+ };
157
+ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref4) {
158
+ var state = _ref4.state,
159
+ pluginState = _ref4.pluginState,
160
+ nodeViewSerializer = _ref4.nodeViewSerializer,
161
+ colorScheme = _ref4.colorScheme,
162
+ intl = _ref4.intl,
163
+ activeIndexPos = _ref4.activeIndexPos,
164
+ api = _ref4.api,
165
+ _ref4$isInverted = _ref4.isInverted,
166
+ isInverted = _ref4$isInverted === void 0 ? false : _ref4$isInverted,
167
+ _ref4$diffType = _ref4.diffType,
168
+ diffType = _ref4$diffType === void 0 ? 'inline' : _ref4$diffType,
169
+ _ref4$hideDeletedDiff = _ref4.hideDeletedDiffs,
170
+ hideDeletedDiffs = _ref4$hideDeletedDiff === void 0 ? false : _ref4$hideDeletedDiff,
171
+ _ref4$hideAddedDiffsU = _ref4.hideAddedDiffsUnderline,
172
+ hideAddedDiffsUnderlineParam = _ref4$hideAddedDiffsU === void 0 ? false : _ref4$hideAddedDiffsU,
173
+ _ref4$showIndicators = _ref4.showIndicators,
174
+ showIndicators = _ref4$showIndicators === void 0 ? false : _ref4$showIndicators,
175
+ smartThresholds = _ref4.smartThresholds,
176
+ _ref4$deletedDiffPlac = _ref4.deletedDiffPlacement,
177
+ deletedDiffPlacement = _ref4$deletedDiffPlac === void 0 ? 'top' : _ref4$deletedDiffPlac,
178
+ _ref4$inlineDeletedDi = _ref4.inlineDeletedDiffPlacement,
179
+ inlineDeletedDiffPlacement = _ref4$inlineDeletedDi === void 0 ? 'before' : _ref4$inlineDeletedDi;
157
180
  var originalDoc = pluginState.originalDoc,
158
181
  steps = pluginState.steps,
159
182
  isDisplayingChanges = pluginState.isDisplayingChanges;
@@ -238,6 +261,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
238
261
  var isInserted = !isInverted;
239
262
  var createDecorationsForChange = function createDecorationsForChange(change, showGranularWithBlock) {
240
263
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
264
+
265
+ // Hoisted because it decides BOTH where the deleted widget is anchored and — since the
266
+ // widget pins whichever end of the range it sits at — how the indicator anchors below are
267
+ // allowed to move.
268
+ var isDeletedWidgetBelow = diffType === 'smart' && (0, _platformFeatureFlags.fg)('platform_editor_ai_smart_diff') && isDeletedContentPlacedBelow({
269
+ change: change,
270
+ deletedDiffPlacement: deletedDiffPlacement,
271
+ inlineDeletedDiffPlacement: inlineDeletedDiffPlacement
272
+ });
241
273
  if (change.inserted.length > 0) {
242
274
  // shouldHideDeleted for block/node decorations: suppressed when isInverted + hideDeletedDiffs,
243
275
  // or when showGranularWithBlock (block reference widget is shown instead).
@@ -282,7 +314,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
282
314
  shouldHideDeleted: shouldHideDeleted,
283
315
  showIndicators: showIndicators,
284
316
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
285
- hasDeletedWidget: willRenderDeletedWidget
317
+ hasDeletedWidget: willRenderDeletedWidget,
318
+ isDeletedWidgetBelow: isDeletedWidgetBelow
286
319
  }))));
287
320
  }
288
321
  } catch (err) {
@@ -302,7 +335,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
302
335
  shouldHideDeleted: shouldHideDeleted,
303
336
  showIndicators: showIndicators,
304
337
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
305
- hasDeletedWidget: willRenderDeletedWidget
338
+ hasDeletedWidget: willRenderDeletedWidget,
339
+ isDeletedWidgetBelow: isDeletedWidgetBelow
306
340
  }))));
307
341
  }
308
342
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)(calculateNodesForBlockDecoration(_objectSpread(_objectSpread({
@@ -335,19 +369,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
335
369
  isInserted: !isInserted,
336
370
  diffType: diffType,
337
371
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
338
- // For `smart` changes, optionally render the deleted content after the new
339
- // content (gray + strikethrough) instead of before it. Two independent
340
- // controls, split by change level:
341
- // - node/paragraph-level: `deletedDiffPlacement` (default `'top'`).
342
- // - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
343
- placeBelow: diffType === 'smart' && (0, _platformFeatureFlags.fg)('platform_editor_ai_smart_diff') && function () {
344
- var level = (0, _helpers.smartChangeLevel)(change);
345
- if (level === 'node' || level === 'paragraph') {
346
- return deletedDiffPlacement === 'bottom';
347
- }
348
- // Inline-level (undefined) and sentence-level changes.
349
- return inlineDeletedDiffPlacement === 'after';
350
- }()
372
+ placeBelow: isDeletedWidgetBelow
351
373
  }), {}, {
352
374
  showIndicators: showIndicators
353
375
  }))));
@@ -361,9 +383,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
361
383
  // getChanges returns a flat Change[] with no per-step grouping, making this count impossible
362
384
  // to derive after the fact without re-introducing per-change metadata.
363
385
  var stepChanges = (0, _diffBySteps.getStepChanges)(originalDoc, steps);
364
- stepChanges.forEach(function (_ref4) {
365
- var isGranular = _ref4.isGranular,
366
- stepChangeList = _ref4.changes;
386
+ stepChanges.forEach(function (_ref5) {
387
+ var isGranular = _ref5.isGranular,
388
+ stepChangeList = _ref5.changes;
367
389
  var granularCount = isGranular ? stepChangeList.length : 0;
368
390
 
369
391
  // Calculate the average ratio of changed content on both A (original) and B (new)
@@ -503,42 +525,42 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
503
525
  };
504
526
  var calculateDiffDecorations = exports.calculateDiffDecorations = (0, _memoizeOne.default)(calculateDiffDecorationsInner,
505
527
  // Cache results unless relevant inputs change
506
- function (_ref5, _ref6) {
507
- var _ref0;
508
- var _ref7 = (0, _slicedToArray2.default)(_ref5, 1),
509
- _ref7$ = _ref7[0],
510
- pluginState = _ref7$.pluginState,
511
- state = _ref7$.state,
512
- colorScheme = _ref7$.colorScheme,
513
- intl = _ref7$.intl,
514
- activeIndexPos = _ref7$.activeIndexPos,
515
- isInverted = _ref7$.isInverted,
516
- diffType = _ref7$.diffType,
517
- hideDeletedDiffs = _ref7$.hideDeletedDiffs,
518
- hideAddedDiffsUnderline = _ref7$.hideAddedDiffsUnderline,
519
- showIndicators = _ref7$.showIndicators,
520
- smartThresholds = _ref7$.smartThresholds,
521
- deletedDiffPlacement = _ref7$.deletedDiffPlacement,
522
- inlineDeletedDiffPlacement = _ref7$.inlineDeletedDiffPlacement;
528
+ function (_ref6, _ref7) {
529
+ var _ref1;
523
530
  var _ref8 = (0, _slicedToArray2.default)(_ref6, 1),
524
531
  _ref8$ = _ref8[0],
525
- lastPluginState = _ref8$.pluginState,
526
- lastState = _ref8$.state,
527
- lastColorScheme = _ref8$.colorScheme,
528
- lastIntl = _ref8$.intl,
529
- lastActiveIndexPos = _ref8$.activeIndexPos,
530
- lastIsInverted = _ref8$.isInverted,
531
- lastDiffType = _ref8$.diffType,
532
- lastHideDeletedDiffs = _ref8$.hideDeletedDiffs,
533
- lastHideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
534
- lastShowIndicators = _ref8$.showIndicators,
535
- lastSmartThresholds = _ref8$.smartThresholds,
536
- lastDeletedDiffPlacement = _ref8$.deletedDiffPlacement,
537
- lastInlineDeletedDiffPlacement = _ref8$.inlineDeletedDiffPlacement;
532
+ pluginState = _ref8$.pluginState,
533
+ state = _ref8$.state,
534
+ colorScheme = _ref8$.colorScheme,
535
+ intl = _ref8$.intl,
536
+ activeIndexPos = _ref8$.activeIndexPos,
537
+ isInverted = _ref8$.isInverted,
538
+ diffType = _ref8$.diffType,
539
+ hideDeletedDiffs = _ref8$.hideDeletedDiffs,
540
+ hideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
541
+ showIndicators = _ref8$.showIndicators,
542
+ smartThresholds = _ref8$.smartThresholds,
543
+ deletedDiffPlacement = _ref8$.deletedDiffPlacement,
544
+ inlineDeletedDiffPlacement = _ref8$.inlineDeletedDiffPlacement;
545
+ var _ref9 = (0, _slicedToArray2.default)(_ref7, 1),
546
+ _ref9$ = _ref9[0],
547
+ lastPluginState = _ref9$.pluginState,
548
+ lastState = _ref9$.state,
549
+ lastColorScheme = _ref9$.colorScheme,
550
+ lastIntl = _ref9$.intl,
551
+ lastActiveIndexPos = _ref9$.activeIndexPos,
552
+ lastIsInverted = _ref9$.isInverted,
553
+ lastDiffType = _ref9$.diffType,
554
+ lastHideDeletedDiffs = _ref9$.hideDeletedDiffs,
555
+ lastHideAddedDiffsUnderline = _ref9$.hideAddedDiffsUnderline,
556
+ lastShowIndicators = _ref9$.showIndicators,
557
+ lastSmartThresholds = _ref9$.smartThresholds,
558
+ lastDeletedDiffPlacement = _ref9$.deletedDiffPlacement,
559
+ lastInlineDeletedDiffPlacement = _ref9$.inlineDeletedDiffPlacement;
538
560
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
539
561
  if ((0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
540
- var _ref9;
541
- return (_ref9 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && (0, _isEqual.default)(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref9 !== void 0 ? _ref9 : false;
562
+ var _ref0;
563
+ return (_ref0 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && (0, _isEqual.default)(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref0 !== void 0 ? _ref0 : false;
542
564
  }
543
- return (_ref0 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref0 !== void 0 ? _ref0 : false;
565
+ return (_ref1 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref1 !== void 0 ? _ref1 : false;
544
566
  });
@@ -55,7 +55,9 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
55
55
  hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn,
56
56
  inlineNodeName = _ref.inlineNodeName,
57
57
  _ref$hasDeletedWidget = _ref.hasDeletedWidget,
58
- hasDeletedWidget = _ref$hasDeletedWidget === void 0 ? false : _ref$hasDeletedWidget;
58
+ hasDeletedWidget = _ref$hasDeletedWidget === void 0 ? false : _ref$hasDeletedWidget,
59
+ _ref$isDeletedWidgetB = _ref.isDeletedWidgetBelow,
60
+ isDeletedWidgetBelow = _ref$isDeletedWidgetB === void 0 ? false : _ref$isDeletedWidgetB;
59
61
  var diffId = crypto.randomUUID();
60
62
  if (shouldHideDeleted) {
61
63
  return [_view.Decoration.inline(change.fromB, change.toB, {
@@ -111,14 +113,23 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
111
113
  // bar doesn't extend into the preceding block's margin.
112
114
  // Skip when the deleted-content widget is rendered — the anchor must
113
115
  // stay at the boundary to keep the indicator continuous.
116
+ //
117
+ // The widget only pins the end of the range it is anchored to. It sits at `change.fromB`
118
+ // by default, but `deletedDiffPlacement: 'bottom'` / `inlineDeletedDiffPlacement: 'after'`
119
+ // move it to `change.toB` so the deleted content reads after the added content. In that
120
+ // case the `from` anchor has no widget beside it any more and must be adjusted inward
121
+ // again, otherwise the over-long indicator bar that CCI-18224 fixed comes back.
114
122
  var anchorFrom = change.fromB;
115
123
  var anchorTo = change.toB;
116
- if (!hasDeletedWidget) {
117
- var _$from$nodeAfter, _$to$nodeBefore;
124
+ if (!hasDeletedWidget || isDeletedWidgetBelow) {
125
+ var _$from$nodeAfter;
118
126
  var $from = doc.resolve(anchorFrom);
119
127
  if (!$from.parent.inlineContent && (_$from$nodeAfter = $from.nodeAfter) !== null && _$from$nodeAfter !== void 0 && _$from$nodeAfter.isTextblock) {
120
128
  anchorFrom = anchorFrom + 1;
121
129
  }
130
+ }
131
+ if (!hasDeletedWidget) {
132
+ var _$to$nodeBefore;
122
133
  var $to = doc.resolve(anchorTo);
123
134
  if (!$to.parent.inlineContent && (_$to$nodeBefore = $to.nodeBefore) !== null && _$to$nodeBefore !== void 0 && _$to$nodeBefore.isTextblock) {
124
135
  anchorTo = anchorTo - 1;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getDeletedWidgets = void 0;
7
+ var _decorationKeys = require("./decorations/decorationKeys");
8
+ var _main = require("./main");
9
+ // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
10
+ // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
11
+
12
+ // The element a deleted-content widget renders, or undefined if it renders via a factory.
13
+ var getWidgetElement = function getWidgetElement(decoration) {
14
+ var _type;
15
+ var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
16
+ toDOM = _ref.toDOM;
17
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
18
+ };
19
+
20
+ /**
21
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
22
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
23
+ * nodes, so this is how the element and the position it is anchored at are recovered.
24
+ *
25
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
26
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
27
+ */
28
+ var getDeletedWidgets = exports.getDeletedWidgets = function getDeletedWidgets(editorState, range) {
29
+ var _showDiffPluginKey$ge;
30
+ var decorations = (_showDiffPluginKey$ge = _main.showDiffPluginKey.getState(editorState)) === null || _showDiffPluginKey$ge === void 0 ? void 0 : _showDiffPluginKey$ge.decorations;
31
+ if (!decorations) {
32
+ return [];
33
+ }
34
+ return decorations.find(range === null || range === void 0 ? void 0 : range.from, range === null || range === void 0 ? void 0 : range.to, function (spec) {
35
+ return (0, _decorationKeys.isDiffDecorationSpec)(spec) && spec.decorationType === 'widget';
36
+ }).reduce(function (widgets, decoration) {
37
+ var element = getWidgetElement(decoration);
38
+ if (element) {
39
+ widgets.push({
40
+ element: element,
41
+ position: decoration.from
42
+ });
43
+ }
44
+ return widgets;
45
+ }, []).sort(function (a, b) {
46
+ return a.position - b.position;
47
+ });
48
+ };
@@ -21,7 +21,7 @@ var _scrollToDiff = require("./scrollToDiff");
21
21
  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; }
22
22
  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) { (0, _defineProperty2.default)(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; }
23
23
  var showDiffPluginKey = exports.showDiffPluginKey = new _state2.PluginKey('showDiffPlugin');
24
- var createPlugin = exports.createPlugin = function createPlugin(config, getIntl, api) {
24
+ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl, api, onEditorView) {
25
25
  (0, _enforceCustomStepRegisters.enforceCustomStepRegisters)();
26
26
  var nodeViewSerializer = new _NodeViewSerializer.NodeViewSerializer({});
27
27
  var setNodeViewSerializer = function setNodeViewSerializer(editorView) {
@@ -162,6 +162,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
162
162
  },
163
163
  view: function view(editorView) {
164
164
  setNodeViewSerializer(editorView);
165
+ onEditorView === null || onEditorView === void 0 || onEditorView(editorView);
165
166
  var isFirst = true;
166
167
  var previousActiveIndex;
167
168
  var cancelPendingScrollToDecoration = null;
@@ -214,6 +215,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
214
215
  var _cancelPendingScrollT3;
215
216
  (_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 || _cancelPendingScrollT3();
216
217
  cancelPendingScrollToDecoration = null;
218
+ onEditorView === null || onEditorView === void 0 || onEditorView(undefined);
217
219
  }
218
220
  };
219
221
  },
@@ -8,6 +8,7 @@ exports.showDiffPlugin = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _react = _interopRequireDefault(require("react"));
10
10
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
11
+ var _getDeletedWidgets2 = require("./pm-plugins/getDeletedWidgets");
11
12
  var _getScrollableDecorations = require("./pm-plugins/getScrollableDecorations");
12
13
  var _main = require("./pm-plugins/main");
13
14
  var _IndicatorBarContentComponent = require("./ui/IndicatorBar/IndicatorBarContentComponent");
@@ -16,8 +17,19 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
16
17
  var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
17
18
  var api = _ref.api,
18
19
  config = _ref.config;
20
+ // Captured from the plugin's view lifecycle (see `createPlugin`) so read-only actions can access
21
+ // the current state without exposing the plugin key to consumers.
22
+ var editorView;
23
+ var setEditorView = function setEditorView(view) {
24
+ editorView = view;
25
+ };
19
26
  return {
20
27
  name: 'showDiff',
28
+ actions: {
29
+ getDeletedWidgets: function getDeletedWidgets(range) {
30
+ return editorView ? (0, _getDeletedWidgets2.getDeletedWidgets)(editorView.state, range) : [];
31
+ }
32
+ },
21
33
  commands: {
22
34
  showDiff: function showDiff(params) {
23
35
  return function (_ref2) {
@@ -64,7 +76,7 @@ var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
64
76
  name: 'showDiffPlugin',
65
77
  plugin: function plugin(_ref6) {
66
78
  var getIntl = _ref6.getIntl;
67
- return (0, _main.createPlugin)(config, getIntl, api);
79
+ return (0, _main.createPlugin)(config, getIntl, api, setEditorView);
68
80
  }
69
81
  }];
70
82
  },
@@ -116,6 +116,30 @@ const calculateNodesForBlockDecoration = ({
116
116
  });
117
117
  return decorations;
118
118
  };
119
+ /**
120
+ * Whether deleted content for `change` renders after the new content instead of before it.
121
+ *
122
+ * show-diff splits this across two options by change granularity, so the level decides which one
123
+ * applies:
124
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
125
+ * node level, so they are governed here too.
126
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
127
+ *
128
+ * Callers are responsible for the `smart` diffType and gate checks.
129
+ */
130
+ export const isDeletedContentPlacedBelow = ({
131
+ change,
132
+ deletedDiffPlacement,
133
+ inlineDeletedDiffPlacement
134
+ }) => {
135
+ const level = smartChangeLevel(change);
136
+ if (level === 'node' || level === 'paragraph') {
137
+ return deletedDiffPlacement === 'bottom';
138
+ }
139
+
140
+ // Inline-level (undefined) and sentence-level changes.
141
+ return inlineDeletedDiffPlacement === 'after';
142
+ };
119
143
  const calculateDiffDecorationsInner = ({
120
144
  state,
121
145
  pluginState,
@@ -212,6 +236,15 @@ const calculateDiffDecorationsInner = ({
212
236
  const isInserted = !isInverted;
213
237
  const createDecorationsForChange = (change, showGranularWithBlock) => {
214
238
  const isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
239
+
240
+ // Hoisted because it decides BOTH where the deleted widget is anchored and — since the
241
+ // widget pins whichever end of the range it sits at — how the indicator anchors below are
242
+ // allowed to move.
243
+ const isDeletedWidgetBelow = diffType === 'smart' && fg('platform_editor_ai_smart_diff') && isDeletedContentPlacedBelow({
244
+ change,
245
+ deletedDiffPlacement,
246
+ inlineDeletedDiffPlacement
247
+ });
215
248
  if (change.inserted.length > 0) {
216
249
  // shouldHideDeleted for block/node decorations: suppressed when isInverted + hideDeletedDiffs,
217
250
  // or when showGranularWithBlock (block reference widget is shown instead).
@@ -250,7 +283,8 @@ const calculateDiffDecorationsInner = ({
250
283
  shouldHideDeleted,
251
284
  showIndicators,
252
285
  hideAddedDiffsUnderline,
253
- hasDeletedWidget: willRenderDeletedWidget
286
+ hasDeletedWidget: willRenderDeletedWidget,
287
+ isDeletedWidgetBelow
254
288
  })
255
289
  }));
256
290
  }
@@ -266,7 +300,8 @@ const calculateDiffDecorationsInner = ({
266
300
  shouldHideDeleted,
267
301
  showIndicators,
268
302
  hideAddedDiffsUnderline,
269
- hasDeletedWidget: willRenderDeletedWidget
303
+ hasDeletedWidget: willRenderDeletedWidget,
304
+ isDeletedWidgetBelow
270
305
  })
271
306
  }));
272
307
  }
@@ -300,19 +335,7 @@ const calculateDiffDecorationsInner = ({
300
335
  isInserted: !isInserted,
301
336
  diffType,
302
337
  hideAddedDiffsUnderline,
303
- // For `smart` changes, optionally render the deleted content after the new
304
- // content (gray + strikethrough) instead of before it. Two independent
305
- // controls, split by change level:
306
- // - node/paragraph-level: `deletedDiffPlacement` (default `'top'`).
307
- // - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
308
- placeBelow: diffType === 'smart' && fg('platform_editor_ai_smart_diff') && (() => {
309
- const level = smartChangeLevel(change);
310
- if (level === 'node' || level === 'paragraph') {
311
- return deletedDiffPlacement === 'bottom';
312
- }
313
- // Inline-level (undefined) and sentence-level changes.
314
- return inlineDeletedDiffPlacement === 'after';
315
- })()
338
+ placeBelow: isDeletedWidgetBelow
316
339
  }),
317
340
  showIndicators
318
341
  }));
@@ -37,7 +37,8 @@ export const createInlineChangedDecoration = ({
37
37
  diffType,
38
38
  hideAddedDiffsUnderline = false,
39
39
  inlineNodeName,
40
- hasDeletedWidget = false
40
+ hasDeletedWidget = false,
41
+ isDeletedWidgetBelow = false
41
42
  }) => {
42
43
  const diffId = crypto.randomUUID();
43
44
  if (shouldHideDeleted) {
@@ -94,14 +95,23 @@ export const createInlineChangedDecoration = ({
94
95
  // bar doesn't extend into the preceding block's margin.
95
96
  // Skip when the deleted-content widget is rendered — the anchor must
96
97
  // stay at the boundary to keep the indicator continuous.
98
+ //
99
+ // The widget only pins the end of the range it is anchored to. It sits at `change.fromB`
100
+ // by default, but `deletedDiffPlacement: 'bottom'` / `inlineDeletedDiffPlacement: 'after'`
101
+ // move it to `change.toB` so the deleted content reads after the added content. In that
102
+ // case the `from` anchor has no widget beside it any more and must be adjusted inward
103
+ // again, otherwise the over-long indicator bar that CCI-18224 fixed comes back.
97
104
  let anchorFrom = change.fromB;
98
105
  let anchorTo = change.toB;
99
- if (!hasDeletedWidget) {
100
- var _$from$nodeAfter, _$to$nodeBefore;
106
+ if (!hasDeletedWidget || isDeletedWidgetBelow) {
107
+ var _$from$nodeAfter;
101
108
  const $from = doc.resolve(anchorFrom);
102
109
  if (!$from.parent.inlineContent && (_$from$nodeAfter = $from.nodeAfter) !== null && _$from$nodeAfter !== void 0 && _$from$nodeAfter.isTextblock) {
103
110
  anchorFrom = anchorFrom + 1;
104
111
  }
112
+ }
113
+ if (!hasDeletedWidget) {
114
+ var _$to$nodeBefore;
105
115
  const $to = doc.resolve(anchorTo);
106
116
  if (!$to.parent.inlineContent && (_$to$nodeBefore = $to.nodeBefore) !== null && _$to$nodeBefore !== void 0 && _$to$nodeBefore.isTextblock) {
107
117
  anchorTo = anchorTo - 1;
@@ -0,0 +1,40 @@
1
+ import { isDiffDecorationSpec } from './decorations/decorationKeys';
2
+ import { showDiffPluginKey } from './main';
3
+
4
+ // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
5
+ // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
6
+
7
+ // The element a deleted-content widget renders, or undefined if it renders via a factory.
8
+ const getWidgetElement = decoration => {
9
+ var _type;
10
+ const {
11
+ toDOM
12
+ } = (_type = decoration.type) !== null && _type !== void 0 ? _type : {};
13
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
14
+ };
15
+
16
+ /**
17
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
18
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
19
+ * nodes, so this is how the element and the position it is anchored at are recovered.
20
+ *
21
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
22
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
23
+ */
24
+ export const getDeletedWidgets = (editorState, range) => {
25
+ var _showDiffPluginKey$ge;
26
+ const decorations = (_showDiffPluginKey$ge = showDiffPluginKey.getState(editorState)) === null || _showDiffPluginKey$ge === void 0 ? void 0 : _showDiffPluginKey$ge.decorations;
27
+ if (!decorations) {
28
+ return [];
29
+ }
30
+ return decorations.find(range === null || range === void 0 ? void 0 : range.from, range === null || range === void 0 ? void 0 : range.to, spec => isDiffDecorationSpec(spec) && spec.decorationType === 'widget').reduce((widgets, decoration) => {
31
+ const element = getWidgetElement(decoration);
32
+ if (element) {
33
+ widgets.push({
34
+ element,
35
+ position: decoration.from
36
+ });
37
+ }
38
+ return widgets;
39
+ }, []).sort((a, b) => a.position - b.position);
40
+ };
@@ -11,7 +11,7 @@ import { isExtendedEnabled } from './isExtendedEnabled';
11
11
  import { NodeViewSerializer } from './NodeViewSerializer';
12
12
  import { scrollToActiveDecoration, scrollToFirstDecoration } from './scrollToDiff';
13
13
  export const showDiffPluginKey = new PluginKey('showDiffPlugin');
14
- export const createPlugin = (config, getIntl, api) => {
14
+ export const createPlugin = (config, getIntl, api, onEditorView) => {
15
15
  enforceCustomStepRegisters();
16
16
  const nodeViewSerializer = new NodeViewSerializer({});
17
17
  const setNodeViewSerializer = editorView => {
@@ -171,6 +171,7 @@ export const createPlugin = (config, getIntl, api) => {
171
171
  },
172
172
  view(editorView) {
173
173
  setNodeViewSerializer(editorView);
174
+ onEditorView === null || onEditorView === void 0 ? void 0 : onEditorView(editorView);
174
175
  let isFirst = true;
175
176
  let previousActiveIndex;
176
177
  let cancelPendingScrollToDecoration = null;
@@ -221,6 +222,7 @@ export const createPlugin = (config, getIntl, api) => {
221
222
  var _cancelPendingScrollT3;
222
223
  (_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 ? void 0 : _cancelPendingScrollT3();
223
224
  cancelPendingScrollToDecoration = null;
225
+ onEditorView === null || onEditorView === void 0 ? void 0 : onEditorView(undefined);
224
226
  }
225
227
  };
226
228
  },