@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.
@@ -1,93 +1,105 @@
1
1
  import React from 'react';
2
2
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
+ import { getDeletedWidgets } from './pm-plugins/getDeletedWidgets';
3
4
  import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
4
5
  import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
5
6
  import { IndicatorBarContentComponent } from './ui/IndicatorBar/IndicatorBarContentComponent';
6
7
  export const showDiffPlugin = ({
7
8
  api,
8
9
  config
9
- }) => ({
10
- name: 'showDiff',
11
- commands: {
12
- showDiff: params => ({
13
- tr
14
- }) => {
15
- if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
16
- var _api$userIntent;
17
- api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('viewingDiff')({
18
- tr
19
- });
20
- }
21
- return tr.setMeta(showDiffPluginKey, {
22
- ...params,
23
- action: 'SHOW_DIFF'
24
- });
10
+ }) => {
11
+ // Captured from the plugin's view lifecycle (see `createPlugin`) so read-only actions can access
12
+ // the current state without exposing the plugin key to consumers.
13
+ let editorView;
14
+ const setEditorView = view => {
15
+ editorView = view;
16
+ };
17
+ return {
18
+ name: 'showDiff',
19
+ actions: {
20
+ getDeletedWidgets: range => editorView ? getDeletedWidgets(editorView.state, range) : []
25
21
  },
26
- hideDiff: ({
27
- tr
28
- }) => {
29
- if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
30
- var _api$userIntent2;
31
- api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default')({
32
- tr
22
+ commands: {
23
+ showDiff: params => ({
24
+ tr
25
+ }) => {
26
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
27
+ var _api$userIntent;
28
+ api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('viewingDiff')({
29
+ tr
30
+ });
31
+ }
32
+ return tr.setMeta(showDiffPluginKey, {
33
+ ...params,
34
+ action: 'SHOW_DIFF'
35
+ });
36
+ },
37
+ hideDiff: ({
38
+ tr
39
+ }) => {
40
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
41
+ var _api$userIntent2;
42
+ api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default')({
43
+ tr
44
+ });
45
+ }
46
+ return tr.setMeta(showDiffPluginKey, {
47
+ steps: [],
48
+ action: 'HIDE_DIFF'
49
+ });
50
+ },
51
+ scrollToNext: ({
52
+ tr
53
+ }) => {
54
+ return tr.setMeta(showDiffPluginKey, {
55
+ action: 'SCROLL_TO_NEXT'
56
+ });
57
+ },
58
+ scrollToPrevious: ({
59
+ tr
60
+ }) => {
61
+ return tr.setMeta(showDiffPluginKey, {
62
+ action: 'SCROLL_TO_PREVIOUS'
33
63
  });
34
64
  }
35
- return tr.setMeta(showDiffPluginKey, {
36
- steps: [],
37
- action: 'HIDE_DIFF'
38
- });
39
65
  },
40
- scrollToNext: ({
41
- tr
42
- }) => {
43
- return tr.setMeta(showDiffPluginKey, {
44
- action: 'SCROLL_TO_NEXT'
45
- });
66
+ pmPlugins() {
67
+ return [{
68
+ name: 'showDiffPlugin',
69
+ plugin: ({
70
+ getIntl
71
+ }) => createPlugin(config, getIntl, api, setEditorView)
72
+ }];
46
73
  },
47
- scrollToPrevious: ({
48
- tr
49
- }) => {
50
- return tr.setMeta(showDiffPluginKey, {
51
- action: 'SCROLL_TO_PREVIOUS'
74
+ contentComponent: () => {
75
+ if (!expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
76
+ return null;
77
+ }
78
+ return /*#__PURE__*/React.createElement(IndicatorBarContentComponent, {
79
+ api: api
52
80
  });
53
- }
54
- },
55
- pmPlugins() {
56
- return [{
57
- name: 'showDiffPlugin',
58
- plugin: ({
59
- getIntl
60
- }) => createPlugin(config, getIntl, api)
61
- }];
62
- },
63
- contentComponent: () => {
64
- if (!expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
65
- return null;
66
- }
67
- return /*#__PURE__*/React.createElement(IndicatorBarContentComponent, {
68
- api: api
69
- });
70
- },
71
- getSharedState: editorState => {
72
- if (!editorState) {
81
+ },
82
+ getSharedState: editorState => {
83
+ if (!editorState) {
84
+ return {
85
+ isDisplayingChanges: false,
86
+ activeIndex: undefined,
87
+ ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
88
+ diffDescriptors: []
89
+ } : {})
90
+ };
91
+ }
92
+ const pluginState = showDiffPluginKey.getState(editorState);
93
+ const decorationCount = getScrollableDecorations(pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations, editorState.doc);
73
94
  return {
74
- isDisplayingChanges: false,
75
- activeIndex: undefined,
95
+ isDisplayingChanges: decorationCount.length > 0,
96
+ activeIndex: pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex,
97
+ numberOfChanges: decorationCount.length,
76
98
  ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
77
- diffDescriptors: []
99
+ diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors,
100
+ showIndicators: pluginState === null || pluginState === void 0 ? void 0 : pluginState.showIndicators
78
101
  } : {})
79
102
  };
80
103
  }
81
- const pluginState = showDiffPluginKey.getState(editorState);
82
- const decorationCount = getScrollableDecorations(pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations, editorState.doc);
83
- return {
84
- isDisplayingChanges: decorationCount.length > 0,
85
- activeIndex: pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex,
86
- numberOfChanges: decorationCount.length,
87
- ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
88
- diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors,
89
- showIndicators: pluginState === null || pluginState === void 0 ? void 0 : pluginState.showIndicators
90
- } : {})
91
- };
92
- }
93
- });
104
+ };
105
+ };
@@ -125,29 +125,52 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
125
125
  });
126
126
  return decorations;
127
127
  };
128
- var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3) {
129
- var state = _ref3.state,
130
- pluginState = _ref3.pluginState,
131
- nodeViewSerializer = _ref3.nodeViewSerializer,
132
- colorScheme = _ref3.colorScheme,
133
- intl = _ref3.intl,
134
- activeIndexPos = _ref3.activeIndexPos,
135
- api = _ref3.api,
136
- _ref3$isInverted = _ref3.isInverted,
137
- isInverted = _ref3$isInverted === void 0 ? false : _ref3$isInverted,
138
- _ref3$diffType = _ref3.diffType,
139
- diffType = _ref3$diffType === void 0 ? 'inline' : _ref3$diffType,
140
- _ref3$hideDeletedDiff = _ref3.hideDeletedDiffs,
141
- hideDeletedDiffs = _ref3$hideDeletedDiff === void 0 ? false : _ref3$hideDeletedDiff,
142
- _ref3$hideAddedDiffsU = _ref3.hideAddedDiffsUnderline,
143
- hideAddedDiffsUnderlineParam = _ref3$hideAddedDiffsU === void 0 ? false : _ref3$hideAddedDiffsU,
144
- _ref3$showIndicators = _ref3.showIndicators,
145
- showIndicators = _ref3$showIndicators === void 0 ? false : _ref3$showIndicators,
146
- smartThresholds = _ref3.smartThresholds,
147
- _ref3$deletedDiffPlac = _ref3.deletedDiffPlacement,
148
- deletedDiffPlacement = _ref3$deletedDiffPlac === void 0 ? 'top' : _ref3$deletedDiffPlac,
149
- _ref3$inlineDeletedDi = _ref3.inlineDeletedDiffPlacement,
150
- inlineDeletedDiffPlacement = _ref3$inlineDeletedDi === void 0 ? 'before' : _ref3$inlineDeletedDi;
128
+ /**
129
+ * Whether deleted content for `change` renders after the new content instead of before it.
130
+ *
131
+ * show-diff splits this across two options by change granularity, so the level decides which one
132
+ * applies:
133
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
134
+ * node level, so they are governed here too.
135
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
136
+ *
137
+ * Callers are responsible for the `smart` diffType and gate checks.
138
+ */
139
+ export var isDeletedContentPlacedBelow = function isDeletedContentPlacedBelow(_ref3) {
140
+ var change = _ref3.change,
141
+ deletedDiffPlacement = _ref3.deletedDiffPlacement,
142
+ inlineDeletedDiffPlacement = _ref3.inlineDeletedDiffPlacement;
143
+ var level = smartChangeLevel(change);
144
+ if (level === 'node' || level === 'paragraph') {
145
+ return deletedDiffPlacement === 'bottom';
146
+ }
147
+
148
+ // Inline-level (undefined) and sentence-level changes.
149
+ return inlineDeletedDiffPlacement === 'after';
150
+ };
151
+ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref4) {
152
+ var state = _ref4.state,
153
+ pluginState = _ref4.pluginState,
154
+ nodeViewSerializer = _ref4.nodeViewSerializer,
155
+ colorScheme = _ref4.colorScheme,
156
+ intl = _ref4.intl,
157
+ activeIndexPos = _ref4.activeIndexPos,
158
+ api = _ref4.api,
159
+ _ref4$isInverted = _ref4.isInverted,
160
+ isInverted = _ref4$isInverted === void 0 ? false : _ref4$isInverted,
161
+ _ref4$diffType = _ref4.diffType,
162
+ diffType = _ref4$diffType === void 0 ? 'inline' : _ref4$diffType,
163
+ _ref4$hideDeletedDiff = _ref4.hideDeletedDiffs,
164
+ hideDeletedDiffs = _ref4$hideDeletedDiff === void 0 ? false : _ref4$hideDeletedDiff,
165
+ _ref4$hideAddedDiffsU = _ref4.hideAddedDiffsUnderline,
166
+ hideAddedDiffsUnderlineParam = _ref4$hideAddedDiffsU === void 0 ? false : _ref4$hideAddedDiffsU,
167
+ _ref4$showIndicators = _ref4.showIndicators,
168
+ showIndicators = _ref4$showIndicators === void 0 ? false : _ref4$showIndicators,
169
+ smartThresholds = _ref4.smartThresholds,
170
+ _ref4$deletedDiffPlac = _ref4.deletedDiffPlacement,
171
+ deletedDiffPlacement = _ref4$deletedDiffPlac === void 0 ? 'top' : _ref4$deletedDiffPlac,
172
+ _ref4$inlineDeletedDi = _ref4.inlineDeletedDiffPlacement,
173
+ inlineDeletedDiffPlacement = _ref4$inlineDeletedDi === void 0 ? 'before' : _ref4$inlineDeletedDi;
151
174
  var originalDoc = pluginState.originalDoc,
152
175
  steps = pluginState.steps,
153
176
  isDisplayingChanges = pluginState.isDisplayingChanges;
@@ -232,6 +255,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
232
255
  var isInserted = !isInverted;
233
256
  var createDecorationsForChange = function createDecorationsForChange(change, showGranularWithBlock) {
234
257
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
258
+
259
+ // Hoisted because it decides BOTH where the deleted widget is anchored and — since the
260
+ // widget pins whichever end of the range it sits at — how the indicator anchors below are
261
+ // allowed to move.
262
+ var isDeletedWidgetBelow = diffType === 'smart' && fg('platform_editor_ai_smart_diff') && isDeletedContentPlacedBelow({
263
+ change: change,
264
+ deletedDiffPlacement: deletedDiffPlacement,
265
+ inlineDeletedDiffPlacement: inlineDeletedDiffPlacement
266
+ });
235
267
  if (change.inserted.length > 0) {
236
268
  // shouldHideDeleted for block/node decorations: suppressed when isInverted + hideDeletedDiffs,
237
269
  // or when showGranularWithBlock (block reference widget is shown instead).
@@ -276,7 +308,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
276
308
  shouldHideDeleted: shouldHideDeleted,
277
309
  showIndicators: showIndicators,
278
310
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
279
- hasDeletedWidget: willRenderDeletedWidget
311
+ hasDeletedWidget: willRenderDeletedWidget,
312
+ isDeletedWidgetBelow: isDeletedWidgetBelow
280
313
  }))));
281
314
  }
282
315
  } catch (err) {
@@ -296,7 +329,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
296
329
  shouldHideDeleted: shouldHideDeleted,
297
330
  showIndicators: showIndicators,
298
331
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
299
- hasDeletedWidget: willRenderDeletedWidget
332
+ hasDeletedWidget: willRenderDeletedWidget,
333
+ isDeletedWidgetBelow: isDeletedWidgetBelow
300
334
  }))));
301
335
  }
302
336
  decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration(_objectSpread(_objectSpread({
@@ -329,19 +363,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
329
363
  isInserted: !isInserted,
330
364
  diffType: diffType,
331
365
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
332
- // For `smart` changes, optionally render the deleted content after the new
333
- // content (gray + strikethrough) instead of before it. Two independent
334
- // controls, split by change level:
335
- // - node/paragraph-level: `deletedDiffPlacement` (default `'top'`).
336
- // - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
337
- placeBelow: diffType === 'smart' && fg('platform_editor_ai_smart_diff') && function () {
338
- var level = smartChangeLevel(change);
339
- if (level === 'node' || level === 'paragraph') {
340
- return deletedDiffPlacement === 'bottom';
341
- }
342
- // Inline-level (undefined) and sentence-level changes.
343
- return inlineDeletedDiffPlacement === 'after';
344
- }()
366
+ placeBelow: isDeletedWidgetBelow
345
367
  }), {}, {
346
368
  showIndicators: showIndicators
347
369
  }))));
@@ -355,9 +377,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
355
377
  // getChanges returns a flat Change[] with no per-step grouping, making this count impossible
356
378
  // to derive after the fact without re-introducing per-change metadata.
357
379
  var stepChanges = getStepChanges(originalDoc, steps);
358
- stepChanges.forEach(function (_ref4) {
359
- var isGranular = _ref4.isGranular,
360
- stepChangeList = _ref4.changes;
380
+ stepChanges.forEach(function (_ref5) {
381
+ var isGranular = _ref5.isGranular,
382
+ stepChangeList = _ref5.changes;
361
383
  var granularCount = isGranular ? stepChangeList.length : 0;
362
384
 
363
385
  // Calculate the average ratio of changed content on both A (original) and B (new)
@@ -497,42 +519,42 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
497
519
  };
498
520
  export var calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner,
499
521
  // Cache results unless relevant inputs change
500
- function (_ref5, _ref6) {
501
- var _ref0;
502
- var _ref7 = _slicedToArray(_ref5, 1),
503
- _ref7$ = _ref7[0],
504
- pluginState = _ref7$.pluginState,
505
- state = _ref7$.state,
506
- colorScheme = _ref7$.colorScheme,
507
- intl = _ref7$.intl,
508
- activeIndexPos = _ref7$.activeIndexPos,
509
- isInverted = _ref7$.isInverted,
510
- diffType = _ref7$.diffType,
511
- hideDeletedDiffs = _ref7$.hideDeletedDiffs,
512
- hideAddedDiffsUnderline = _ref7$.hideAddedDiffsUnderline,
513
- showIndicators = _ref7$.showIndicators,
514
- smartThresholds = _ref7$.smartThresholds,
515
- deletedDiffPlacement = _ref7$.deletedDiffPlacement,
516
- inlineDeletedDiffPlacement = _ref7$.inlineDeletedDiffPlacement;
522
+ function (_ref6, _ref7) {
523
+ var _ref1;
517
524
  var _ref8 = _slicedToArray(_ref6, 1),
518
525
  _ref8$ = _ref8[0],
519
- lastPluginState = _ref8$.pluginState,
520
- lastState = _ref8$.state,
521
- lastColorScheme = _ref8$.colorScheme,
522
- lastIntl = _ref8$.intl,
523
- lastActiveIndexPos = _ref8$.activeIndexPos,
524
- lastIsInverted = _ref8$.isInverted,
525
- lastDiffType = _ref8$.diffType,
526
- lastHideDeletedDiffs = _ref8$.hideDeletedDiffs,
527
- lastHideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
528
- lastShowIndicators = _ref8$.showIndicators,
529
- lastSmartThresholds = _ref8$.smartThresholds,
530
- lastDeletedDiffPlacement = _ref8$.deletedDiffPlacement,
531
- lastInlineDeletedDiffPlacement = _ref8$.inlineDeletedDiffPlacement;
526
+ pluginState = _ref8$.pluginState,
527
+ state = _ref8$.state,
528
+ colorScheme = _ref8$.colorScheme,
529
+ intl = _ref8$.intl,
530
+ activeIndexPos = _ref8$.activeIndexPos,
531
+ isInverted = _ref8$.isInverted,
532
+ diffType = _ref8$.diffType,
533
+ hideDeletedDiffs = _ref8$.hideDeletedDiffs,
534
+ hideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
535
+ showIndicators = _ref8$.showIndicators,
536
+ smartThresholds = _ref8$.smartThresholds,
537
+ deletedDiffPlacement = _ref8$.deletedDiffPlacement,
538
+ inlineDeletedDiffPlacement = _ref8$.inlineDeletedDiffPlacement;
539
+ var _ref9 = _slicedToArray(_ref7, 1),
540
+ _ref9$ = _ref9[0],
541
+ lastPluginState = _ref9$.pluginState,
542
+ lastState = _ref9$.state,
543
+ lastColorScheme = _ref9$.colorScheme,
544
+ lastIntl = _ref9$.intl,
545
+ lastActiveIndexPos = _ref9$.activeIndexPos,
546
+ lastIsInverted = _ref9$.isInverted,
547
+ lastDiffType = _ref9$.diffType,
548
+ lastHideDeletedDiffs = _ref9$.hideDeletedDiffs,
549
+ lastHideAddedDiffsUnderline = _ref9$.hideAddedDiffsUnderline,
550
+ lastShowIndicators = _ref9$.showIndicators,
551
+ lastSmartThresholds = _ref9$.smartThresholds,
552
+ lastDeletedDiffPlacement = _ref9$.deletedDiffPlacement,
553
+ lastInlineDeletedDiffPlacement = _ref9$.inlineDeletedDiffPlacement;
532
554
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
533
555
  if (isExtendedEnabled(diffType)) {
534
- var _ref9;
535
- return (_ref9 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref9 !== void 0 ? _ref9 : false;
556
+ var _ref0;
557
+ return (_ref0 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref0 !== void 0 ? _ref0 : false;
536
558
  }
537
- return (_ref0 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref0 !== void 0 ? _ref0 : false;
559
+ return (_ref1 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref1 !== void 0 ? _ref1 : false;
538
560
  });
@@ -48,7 +48,9 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
48
48
  hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn,
49
49
  inlineNodeName = _ref.inlineNodeName,
50
50
  _ref$hasDeletedWidget = _ref.hasDeletedWidget,
51
- hasDeletedWidget = _ref$hasDeletedWidget === void 0 ? false : _ref$hasDeletedWidget;
51
+ hasDeletedWidget = _ref$hasDeletedWidget === void 0 ? false : _ref$hasDeletedWidget,
52
+ _ref$isDeletedWidgetB = _ref.isDeletedWidgetBelow,
53
+ isDeletedWidgetBelow = _ref$isDeletedWidgetB === void 0 ? false : _ref$isDeletedWidgetB;
52
54
  var diffId = crypto.randomUUID();
53
55
  if (shouldHideDeleted) {
54
56
  return [Decoration.inline(change.fromB, change.toB, {
@@ -104,14 +106,23 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
104
106
  // bar doesn't extend into the preceding block's margin.
105
107
  // Skip when the deleted-content widget is rendered — the anchor must
106
108
  // stay at the boundary to keep the indicator continuous.
109
+ //
110
+ // The widget only pins the end of the range it is anchored to. It sits at `change.fromB`
111
+ // by default, but `deletedDiffPlacement: 'bottom'` / `inlineDeletedDiffPlacement: 'after'`
112
+ // move it to `change.toB` so the deleted content reads after the added content. In that
113
+ // case the `from` anchor has no widget beside it any more and must be adjusted inward
114
+ // again, otherwise the over-long indicator bar that CCI-18224 fixed comes back.
107
115
  var anchorFrom = change.fromB;
108
116
  var anchorTo = change.toB;
109
- if (!hasDeletedWidget) {
110
- var _$from$nodeAfter, _$to$nodeBefore;
117
+ if (!hasDeletedWidget || isDeletedWidgetBelow) {
118
+ var _$from$nodeAfter;
111
119
  var $from = doc.resolve(anchorFrom);
112
120
  if (!$from.parent.inlineContent && (_$from$nodeAfter = $from.nodeAfter) !== null && _$from$nodeAfter !== void 0 && _$from$nodeAfter.isTextblock) {
113
121
  anchorFrom = anchorFrom + 1;
114
122
  }
123
+ }
124
+ if (!hasDeletedWidget) {
125
+ var _$to$nodeBefore;
115
126
  var $to = doc.resolve(anchorTo);
116
127
  if (!$to.parent.inlineContent && (_$to$nodeBefore = $to.nodeBefore) !== null && _$to$nodeBefore !== void 0 && _$to$nodeBefore.isTextblock) {
117
128
  anchorTo = anchorTo - 1;
@@ -0,0 +1,43 @@
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
+ var getWidgetElement = function getWidgetElement(decoration) {
9
+ var _type;
10
+ var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
11
+ toDOM = _ref.toDOM;
12
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
13
+ };
14
+
15
+ /**
16
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
17
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
18
+ * nodes, so this is how the element and the position it is anchored at are recovered.
19
+ *
20
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
21
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
22
+ */
23
+ export var getDeletedWidgets = function getDeletedWidgets(editorState, range) {
24
+ var _showDiffPluginKey$ge;
25
+ var decorations = (_showDiffPluginKey$ge = showDiffPluginKey.getState(editorState)) === null || _showDiffPluginKey$ge === void 0 ? void 0 : _showDiffPluginKey$ge.decorations;
26
+ if (!decorations) {
27
+ return [];
28
+ }
29
+ return decorations.find(range === null || range === void 0 ? void 0 : range.from, range === null || range === void 0 ? void 0 : range.to, function (spec) {
30
+ return isDiffDecorationSpec(spec) && spec.decorationType === 'widget';
31
+ }).reduce(function (widgets, decoration) {
32
+ var element = getWidgetElement(decoration);
33
+ if (element) {
34
+ widgets.push({
35
+ element: element,
36
+ position: decoration.from
37
+ });
38
+ }
39
+ return widgets;
40
+ }, []).sort(function (a, b) {
41
+ return a.position - b.position;
42
+ });
43
+ };
@@ -14,7 +14,7 @@ import { isExtendedEnabled } from './isExtendedEnabled';
14
14
  import { NodeViewSerializer } from './NodeViewSerializer';
15
15
  import { scrollToActiveDecoration, scrollToFirstDecoration } from './scrollToDiff';
16
16
  export var showDiffPluginKey = new PluginKey('showDiffPlugin');
17
- export var createPlugin = function createPlugin(config, getIntl, api) {
17
+ export var createPlugin = function createPlugin(config, getIntl, api, onEditorView) {
18
18
  enforceCustomStepRegisters();
19
19
  var nodeViewSerializer = new NodeViewSerializer({});
20
20
  var setNodeViewSerializer = function setNodeViewSerializer(editorView) {
@@ -155,6 +155,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
155
155
  },
156
156
  view: function view(editorView) {
157
157
  setNodeViewSerializer(editorView);
158
+ onEditorView === null || onEditorView === void 0 || onEditorView(editorView);
158
159
  var isFirst = true;
159
160
  var previousActiveIndex;
160
161
  var cancelPendingScrollToDecoration = null;
@@ -207,6 +208,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
207
208
  var _cancelPendingScrollT3;
208
209
  (_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 || _cancelPendingScrollT3();
209
210
  cancelPendingScrollToDecoration = null;
211
+ onEditorView === null || onEditorView === void 0 || onEditorView(undefined);
210
212
  }
211
213
  };
212
214
  },
@@ -3,14 +3,26 @@ 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 React from 'react';
5
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
6
+ import { getDeletedWidgets as _getDeletedWidgets } from './pm-plugins/getDeletedWidgets';
6
7
  import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
7
8
  import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
8
9
  import { IndicatorBarContentComponent } from './ui/IndicatorBar/IndicatorBarContentComponent';
9
10
  export var showDiffPlugin = function showDiffPlugin(_ref) {
10
11
  var api = _ref.api,
11
12
  config = _ref.config;
13
+ // Captured from the plugin's view lifecycle (see `createPlugin`) so read-only actions can access
14
+ // the current state without exposing the plugin key to consumers.
15
+ var editorView;
16
+ var setEditorView = function setEditorView(view) {
17
+ editorView = view;
18
+ };
12
19
  return {
13
20
  name: 'showDiff',
21
+ actions: {
22
+ getDeletedWidgets: function getDeletedWidgets(range) {
23
+ return editorView ? _getDeletedWidgets(editorView.state, range) : [];
24
+ }
25
+ },
14
26
  commands: {
15
27
  showDiff: function showDiff(params) {
16
28
  return function (_ref2) {
@@ -57,7 +69,7 @@ export var showDiffPlugin = function showDiffPlugin(_ref) {
57
69
  name: 'showDiffPlugin',
58
70
  plugin: function plugin(_ref6) {
59
71
  var getIntl = _ref6.getIntl;
60
- return createPlugin(config, getIntl, api);
72
+ return createPlugin(config, getIntl, api, setEditorView);
61
73
  }
62
74
  }];
63
75
  },
@@ -1 +1 @@
1
- export type { DeletedDiffPlacement, DiffParams, DiffType, PMDiffParams, ShowDiffPlugin, SmartDiffThresholds, } from '../showDiffPluginType';
1
+ export type { DeletedDiffPlacement, DeletedDiffWidget, DiffParams, DiffType, PMDiffParams, ShowDiffPlugin, SmartDiffThresholds, } from '../showDiffPluginType';
@@ -1,4 +1,5 @@
1
1
  import { type MemoizedFn } from 'memoize-one';
2
+ import { type Change } from 'prosemirror-changeset';
2
3
  import type { IntlShape } from 'react-intl';
3
4
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
5
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
@@ -10,6 +11,22 @@ type CalculatedDiffs = {
10
11
  decorations: DecorationSet;
11
12
  diffDescriptors: DiffDescriptor[];
12
13
  };
14
+ /**
15
+ * Whether deleted content for `change` renders after the new content instead of before it.
16
+ *
17
+ * show-diff splits this across two options by change granularity, so the level decides which one
18
+ * applies:
19
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
20
+ * node level, so they are governed here too.
21
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
22
+ *
23
+ * Callers are responsible for the `smart` diffType and gate checks.
24
+ */
25
+ export declare const isDeletedContentPlacedBelow: ({ change, deletedDiffPlacement, inlineDeletedDiffPlacement, }: {
26
+ change: Change;
27
+ deletedDiffPlacement?: DeletedDiffPlacement;
28
+ inlineDeletedDiffPlacement?: InlineDeletedDiffPlacement;
29
+ }) => boolean;
13
30
  export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState, nodeViewSerializer, colorScheme, intl, activeIndexPos, api, hideDeletedDiffs, hideAddedDiffsUnderline, showIndicators, }: {
14
31
  activeIndexPos?: {
15
32
  from: number;
@@ -8,7 +8,7 @@ import type { InlineAttrChangeNodeName } from './utils/getAttrChangeRanges';
8
8
  * @param change Changeset "change" containing information about the change content + range
9
9
  * @returns Prosemirror inline decoration
10
10
  */
11
- export declare const createInlineChangedDecoration: ({ change, colorScheme, isActive, isInserted, isAtomicInlineNode, shouldHideDeleted, showIndicators, doc, diffType, hideAddedDiffsUnderline, inlineNodeName, hasDeletedWidget, }: {
11
+ export declare const createInlineChangedDecoration: ({ change, colorScheme, isActive, isInserted, isAtomicInlineNode, shouldHideDeleted, showIndicators, doc, diffType, hideAddedDiffsUnderline, inlineNodeName, hasDeletedWidget, isDeletedWidgetBelow, }: {
12
12
  change: {
13
13
  fromB: number;
14
14
  toB: number;
@@ -21,6 +21,7 @@ export declare const createInlineChangedDecoration: ({ change, colorScheme, isAc
21
21
  inlineNodeName?: InlineAttrChangeNodeName;
22
22
  isActive?: boolean;
23
23
  isAtomicInlineNode?: boolean;
24
+ isDeletedWidgetBelow?: boolean;
24
25
  isInserted?: boolean;
25
26
  shouldHideDeleted?: boolean;
26
27
  showIndicators?: boolean;
@@ -0,0 +1,14 @@
1
+ import type { EditorState } from 'prosemirror-state';
2
+ import type { DeletedDiffWidget } from '../showDiffPluginType';
3
+ /**
4
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
5
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
6
+ * nodes, so this is how the element and the position it is anchored at are recovered.
7
+ *
8
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
9
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
10
+ */
11
+ export declare const getDeletedWidgets: (editorState: EditorState, range?: {
12
+ from: number;
13
+ to: number;
14
+ }) => DeletedDiffWidget[];
@@ -4,6 +4,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
4
  import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
7
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
8
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
9
  import type { DeletedDiffPlacement, DiffDescriptor, DiffParams, DiffType, InlineDeletedDiffPlacement, ShowDiffPlugin, SmartDiffThresholds } from '../showDiffPluginType';
9
10
  export declare const showDiffPluginKey: PluginKey<ShowDiffPluginState>;
@@ -49,4 +50,4 @@ export type ShowDiffPluginState = {
49
50
  smartThresholds?: Partial<SmartDiffThresholds>;
50
51
  steps: ProseMirrorStep[];
51
52
  };
52
- export declare const createPlugin: (config: DiffParams | undefined, getIntl: () => IntlShape, api: ExtractInjectionAPI<ShowDiffPlugin> | undefined) => SafePlugin<ShowDiffPluginState>;
53
+ export declare const createPlugin: (config: DiffParams | undefined, getIntl: () => IntlShape, api: ExtractInjectionAPI<ShowDiffPlugin> | undefined, onEditorView?: (editorView: EditorView | undefined) => void) => SafePlugin<ShowDiffPluginState>;