@atlaskit/editor-plugin-show-diff 10.0.2 → 10.1.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +25 -8
  3. package/dist/cjs/pm-plugins/decorations/createAnchorDecorationWidgets.js +209 -0
  4. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +17 -2
  5. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +19 -3
  6. package/dist/cjs/pm-plugins/decorations/decorationKeys.js +81 -28
  7. package/dist/cjs/pm-plugins/getScrollableDecorations.js +32 -23
  8. package/dist/cjs/pm-plugins/main.js +8 -6
  9. package/dist/cjs/pm-plugins/scrollToDiff.js +5 -6
  10. package/dist/cjs/showDiffPlugin.js +12 -1
  11. package/dist/cjs/ui/IndicatorBar/IndicatorBar.compiled.css +9 -0
  12. package/dist/cjs/ui/IndicatorBar/IndicatorBar.js +33 -0
  13. package/dist/cjs/ui/IndicatorBar/IndicatorBarContentComponent.js +87 -0
  14. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +23 -8
  15. package/dist/es2019/pm-plugins/decorations/createAnchorDecorationWidgets.js +205 -0
  16. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +14 -2
  17. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +19 -4
  18. package/dist/es2019/pm-plugins/decorations/decorationKeys.js +64 -14
  19. package/dist/es2019/pm-plugins/getScrollableDecorations.js +31 -25
  20. package/dist/es2019/pm-plugins/main.js +8 -6
  21. package/dist/es2019/pm-plugins/scrollToDiff.js +6 -7
  22. package/dist/es2019/showDiffPlugin.js +12 -1
  23. package/dist/es2019/ui/IndicatorBar/IndicatorBar.compiled.css +9 -0
  24. package/dist/es2019/ui/IndicatorBar/IndicatorBar.js +24 -0
  25. package/dist/es2019/ui/IndicatorBar/IndicatorBarContentComponent.js +82 -0
  26. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +25 -8
  27. package/dist/esm/pm-plugins/decorations/createAnchorDecorationWidgets.js +203 -0
  28. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +16 -2
  29. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +20 -4
  30. package/dist/esm/pm-plugins/decorations/decorationKeys.js +78 -27
  31. package/dist/esm/pm-plugins/getScrollableDecorations.js +33 -24
  32. package/dist/esm/pm-plugins/main.js +8 -6
  33. package/dist/esm/pm-plugins/scrollToDiff.js +6 -7
  34. package/dist/esm/showDiffPlugin.js +12 -1
  35. package/dist/esm/ui/IndicatorBar/IndicatorBar.compiled.css +9 -0
  36. package/dist/esm/ui/IndicatorBar/IndicatorBar.js +25 -0
  37. package/dist/esm/ui/IndicatorBar/IndicatorBarContentComponent.js +80 -0
  38. package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +2 -1
  39. package/dist/types/pm-plugins/decorations/createAnchorDecorationWidgets.d.ts +38 -0
  40. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +4 -1
  41. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +2 -1
  42. package/dist/types/pm-plugins/decorations/decorationKeys.d.ts +56 -17
  43. package/dist/types/pm-plugins/main.d.ts +1 -0
  44. package/dist/types/pm-plugins/scrollToDiff.d.ts +2 -2
  45. package/dist/types/showDiffPluginType.d.ts +8 -0
  46. package/dist/types/ui/IndicatorBar/IndicatorBar.d.ts +10 -0
  47. package/dist/types/ui/IndicatorBar/IndicatorBarContentComponent.d.ts +17 -0
  48. package/package.json +6 -5
@@ -0,0 +1,203 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ import { buildAnchorDecorationKey, buildAnchorDecorationSpec, AnchorDocMarginKey, AnchorTypeKey } from './decorationKeys';
3
+ var SIDE = 1;
4
+ var findPosAfterLastChild = function findPosAfterLastChild(node, nodeStart) {
5
+ if (!node) {
6
+ return undefined;
7
+ }
8
+ var lastChild = node.lastChild;
9
+ if (!lastChild) {
10
+ return undefined;
11
+ }
12
+ var lastChildStart = nodeStart + node.content.size - lastChild.nodeSize;
13
+ return lastChildStart + lastChild.nodeSize;
14
+ };
15
+
16
+ /**
17
+ * Handles edge cases for block nodes whose inline content can exceed the doc
18
+ * margin (tables, layouts, expands). Returns an adjusted position to use as
19
+ * the left anchor, or `undefined` when no adjustment is needed.
20
+ */
21
+ var edgeCases = function edgeCases(doc, from) {
22
+ var $from = doc.resolve(from);
23
+ var docLevelNode = $from.node(1);
24
+ if (!docLevelNode) {
25
+ return undefined;
26
+ }
27
+ switch (docLevelNode.type.name) {
28
+ /**
29
+ * For resizable blocks, inline content can exceed the doc margin.
30
+ * The widgets need to be placed inside the block as resizing the block will
31
+ * exceed the block container :')
32
+ */
33
+ case 'table':
34
+ {
35
+ var lastRow = docLevelNode.lastChild;
36
+ if (!lastRow) {
37
+ return undefined;
38
+ }
39
+ var lastRowStart = $from.start(1) + docLevelNode.content.size - lastRow.nodeSize;
40
+ var firstCellOfLastRow = lastRow.firstChild;
41
+ var tableAnchorPos = findPosAfterLastChild(firstCellOfLastRow, lastRowStart + 1);
42
+ if (tableAnchorPos === undefined) {
43
+ return undefined;
44
+ }
45
+ return {
46
+ /**
47
+ * We use the last row because the first row could be a sticky header -
48
+ * when it becomes sticky the anchor won't be defined since it will be rendered
49
+ * outside of the context
50
+ */
51
+ pos: tableAnchorPos,
52
+ leftMargin: "var(--ds-space-negative-025, -2px)",
53
+ side: -1
54
+ };
55
+ }
56
+ case 'expand':
57
+ {
58
+ var expandAnchorPos = findPosAfterLastChild(docLevelNode, $from.start(1));
59
+ if (expandAnchorPos === undefined) {
60
+ return undefined;
61
+ }
62
+ return {
63
+ pos: expandAnchorPos,
64
+ leftMargin: "var(--ds-space-0, 0px)",
65
+ side: -1
66
+ };
67
+ }
68
+ case 'layoutSection':
69
+ {
70
+ var firstLayoutColumn = docLevelNode.firstChild;
71
+ var layoutAnchorPos = findPosAfterLastChild(firstLayoutColumn, $from.start(1) + 1);
72
+ if (layoutAnchorPos === undefined) {
73
+ return undefined;
74
+ }
75
+ return {
76
+ pos: layoutAnchorPos,
77
+ leftMargin: "var(--ds-space-negative-025, -2px)",
78
+ side: 1
79
+ };
80
+ }
81
+ default:
82
+ return undefined;
83
+ }
84
+ };
85
+
86
+ /**
87
+ * Create a widget that marks the start of the doc margin.
88
+ * This is used to determine the position of the inline indicators
89
+ * when the inline content exceeds the doc margin.
90
+ */
91
+ export var createDocMarginAnchorWidget = function createDocMarginAnchorWidget() {
92
+ return Decoration.widget(0, function () {
93
+ var span = document.createElement('span');
94
+ span.style.setProperty('anchor-name', "--".concat(AnchorDocMarginKey));
95
+ return span;
96
+ }, buildAnchorDecorationSpec({
97
+ anchorType: AnchorTypeKey.docMargin,
98
+ side: SIDE
99
+ }));
100
+ };
101
+
102
+ /**
103
+ * Creates an invisible left anchor widget for a diff inside a resizable block
104
+ * node (table, layout, expand), whose inline content can exceed the doc margin.
105
+ * Resolves the edge-case position from `doc`/`from`; returns `undefined` when
106
+ * the diff is not inside such a node and no left anchor is needed.
107
+ *
108
+ * The span is given an `anchor-name` (keyed by `diffId`) and positioned in the
109
+ * doc margin so the `IndicatorBar` can align its left edge against it via CSS
110
+ * anchor positioning. Shared by inline and node (widget) diff decorations.
111
+ */
112
+ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
113
+ var doc = _ref.doc,
114
+ from = _ref.from,
115
+ diffId = _ref.diffId;
116
+ var edgeCase = edgeCases(doc, from);
117
+ if (edgeCase === undefined) {
118
+ return undefined;
119
+ }
120
+ var leftAnchorKey = buildAnchorDecorationKey({
121
+ diffId: diffId,
122
+ anchorType: AnchorTypeKey.left
123
+ });
124
+ return Decoration.widget(edgeCase.pos, function () {
125
+ var span = document.createElement('span');
126
+ span.style.setProperty('anchor-name', "--".concat(leftAnchorKey));
127
+ span.style.setProperty('position', 'absolute');
128
+ span.style.setProperty('left', edgeCase.leftMargin);
129
+ return span;
130
+ }, buildAnchorDecorationSpec({
131
+ diffId: diffId,
132
+ anchorType: AnchorTypeKey.left,
133
+ side: edgeCase.side * SIDE
134
+ }));
135
+ };
136
+ var isFullNodeRange = function isFullNodeRange(doc, from, to) {
137
+ var matchesFullNodeRange = false;
138
+ doc.nodesBetween(from, to, function (node, pos) {
139
+ if (pos === from && pos + node.nodeSize === to) {
140
+ matchesFullNodeRange = true;
141
+ return false;
142
+ }
143
+ return true;
144
+ });
145
+ return matchesFullNodeRange;
146
+ };
147
+ /**
148
+ * Creates invisible anchor widgets for a single inline diff range so that the
149
+ * `IndicatorBar` can use CSS anchor positioning to align itself with the diff.
150
+ *
151
+ * - A `from` anchor is placed at the start of the range (top of the bar).
152
+ * - A `to` anchor is placed at the end of the range (bottom of the bar).
153
+ * - An optional `left` anchor is placed before the first textblock when the
154
+ * diff is inside a resizable block node (table, layout, expand).
155
+ */
156
+ export var createInlineIndicatorAnchorWidgets = function createInlineIndicatorAnchorWidgets(_ref2) {
157
+ var doc = _ref2.doc,
158
+ from = _ref2.from,
159
+ to = _ref2.to,
160
+ diffId = _ref2.diffId;
161
+ if (isFullNodeRange(doc, from, to)) {
162
+ return [];
163
+ }
164
+ var leftAnchor = createLeftAnchorWidget({
165
+ doc: doc,
166
+ from: from,
167
+ diffId: diffId
168
+ });
169
+ var maybeLeftAnchor = leftAnchor ? [leftAnchor] : [];
170
+
171
+ /**
172
+ * Two widgets mark the start and end of the inline range so the
173
+ * IndicatorBar can determine top/bottom even when the decoration
174
+ * spans multiple blocks.
175
+ */
176
+ var fromAnchorKey = buildAnchorDecorationKey({
177
+ diffId: diffId,
178
+ anchorType: AnchorTypeKey.from
179
+ });
180
+ var fromWidget = Decoration.widget(from, function () {
181
+ var span = document.createElement('span');
182
+ span.style.setProperty('anchor-name', "--".concat(fromAnchorKey));
183
+ return span;
184
+ }, buildAnchorDecorationSpec({
185
+ diffId: diffId,
186
+ anchorType: AnchorTypeKey.from,
187
+ side: 1
188
+ }));
189
+ var toAnchorKey = buildAnchorDecorationKey({
190
+ diffId: diffId,
191
+ anchorType: AnchorTypeKey.to
192
+ });
193
+ var toWidget = Decoration.widget(to, function () {
194
+ var span = document.createElement('span');
195
+ span.style.setProperty('anchor-name', "--".concat(toAnchorKey));
196
+ return span;
197
+ }, buildAnchorDecorationSpec({
198
+ diffId: diffId,
199
+ anchorType: AnchorTypeKey.to,
200
+ side: -1
201
+ }));
202
+ return [fromWidget, toWidget].concat(maybeLeftAnchor);
203
+ };
@@ -1,8 +1,10 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
4
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
5
  import { editingStyle, editingStyleExtended, editingStyleActive, editingStyleActiveExtended, deletedContentStyle, deletedContentStyleActive, deletedInlineContentStyleExtended } from './colorSchemes/standard';
5
6
  import { traditionalInsertStyle, traditionalInsertStyleActive, getDeletedTraditionalInlineStyle } from './colorSchemes/traditional';
7
+ import { createInlineIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
6
8
  import { buildDiffDecorationSpec } from './decorationKeys';
7
9
  var displayNoneStyle = convertToInlineCss({
8
10
  display: 'none'
@@ -22,7 +24,10 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
22
24
  _ref$isInserted = _ref.isInserted,
23
25
  isInserted = _ref$isInserted === void 0 ? true : _ref$isInserted,
24
26
  _ref$shouldHideDelete = _ref.shouldHideDeleted,
25
- shouldHideDeleted = _ref$shouldHideDelete === void 0 ? false : _ref$shouldHideDelete;
27
+ shouldHideDeleted = _ref$shouldHideDelete === void 0 ? false : _ref$shouldHideDelete,
28
+ _ref$showIndicators = _ref.showIndicators,
29
+ showIndicators = _ref$showIndicators === void 0 ? false : _ref$showIndicators,
30
+ doc = _ref.doc;
26
31
  var diffId = crypto.randomUUID();
27
32
  if (shouldHideDeleted) {
28
33
  return [Decoration.inline(change.fromB, change.toB, {
@@ -61,7 +66,7 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
61
66
  style = isActive ? editingStyleActive : editingStyle;
62
67
  }
63
68
  }
64
- return [Decoration.inline(change.fromB, change.toB, {
69
+ var decorations = [Decoration.inline(change.fromB, change.toB, {
65
70
  style: style,
66
71
  'data-testid': 'show-diff-changed-decoration'
67
72
  }, buildDiffDecorationSpec({
@@ -69,4 +74,13 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
69
74
  diffId: diffId,
70
75
  isActive: isActive
71
76
  }))];
77
+ if (showIndicators && doc && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
78
+ decorations.push.apply(decorations, _toConsumableArray(createInlineIndicatorAnchorWidgets({
79
+ doc: doc,
80
+ from: change.fromB,
81
+ to: change.toB,
82
+ diffId: diffId
83
+ })));
84
+ }
85
+ return decorations;
72
86
  };
@@ -7,8 +7,9 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
8
  import { editingStyle, editingStyleExtended, editingStyleActive, editingStyleActiveExtended, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleUnbounded, deletedInlineContentStyleExtended } from './colorSchemes/standard';
9
9
  import { traditionalInsertStyle, traditionalInsertStyleActive, getDeletedTraditionalInlineStyle, deletedTraditionalContentStyleUnbounded, deletedTraditionalContentStyleUnboundedActive } from './colorSchemes/traditional';
10
+ import { createLeftAnchorWidget } from './createAnchorDecorationWidgets';
10
11
  import { createChangedRowDecorationWidgets } from './createChangedRowDecorationWidgets';
11
- import { buildDiffDecorationSpec } from './decorationKeys';
12
+ import { buildDiffDecorationSpec, buildAnchorDecorationKey } from './decorationKeys';
12
13
  import { findSafeInsertPos } from './utils/findSafeInsertPos';
13
14
  import { wrapBlockNodeView } from './utils/wrapBlockNodeView';
14
15
  var getDeletedContentStyleUnbounded = function getDeletedContentStyleUnbounded(colorScheme) {
@@ -107,7 +108,9 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
107
108
  intl = _ref2.intl,
108
109
  activeIndexPos = _ref2.activeIndexPos,
109
110
  _ref2$isInserted = _ref2.isInserted,
110
- isInserted = _ref2$isInserted === void 0 ? false : _ref2$isInserted;
111
+ isInserted = _ref2$isInserted === void 0 ? false : _ref2$isInserted,
112
+ _ref2$showIndicators = _ref2.showIndicators,
113
+ showIndicators = _ref2$showIndicators === void 0 ? false : _ref2$showIndicators;
111
114
  var slice = doc.slice(change.fromA, change.toA);
112
115
  var shouldSkipDeletedEmptyParagraphDecoration = !isInserted && (slice === null || slice === void 0 || (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.childCount) === 1 && (slice === null || slice === void 0 || (_slice$content2 = slice.content) === null || _slice$content2 === void 0 || (_slice$content2 = _slice$content2.firstChild) === null || _slice$content2 === void 0 ? void 0 : _slice$content2.type.name) === 'paragraph' && (slice === null || slice === void 0 || (_slice$content3 = slice.content) === null || _slice$content3 === void 0 || (_slice$content3 = _slice$content3.firstChild) === null || _slice$content3 === void 0 ? void 0 : _slice$content3.content.size) === 0;
113
116
  // Widget decoration used for deletions as the content is not in the document
@@ -144,6 +147,8 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
144
147
 
145
148
  // For non-table content, use the existing span wrapper approach
146
149
  var dom = document.createElement('span');
150
+ var diffId = crypto.randomUUID();
151
+ var decorations = [];
147
152
 
148
153
  /*
149
154
  * The thinking is we separate out the fragment we got from doc.slice
@@ -249,8 +254,19 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
249
254
  }
250
255
  });
251
256
  dom.setAttribute('data-testid', 'show-diff-deleted-decoration');
252
- var diffId = crypto.randomUUID();
253
- var decorations = [];
257
+ if (showIndicators && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
258
+ var leftAnchor = createLeftAnchorWidget({
259
+ doc: newDoc,
260
+ from: safeInsertPos,
261
+ diffId: diffId
262
+ });
263
+ dom.style.setProperty('anchor-name', "--".concat(buildAnchorDecorationKey({
264
+ diffId: diffId
265
+ })));
266
+ if (leftAnchor) {
267
+ decorations.push(leftAnchor);
268
+ }
269
+ }
254
270
  decorations.push(Decoration.widget(safeInsertPos, dom, buildDiffDecorationSpec(_objectSpread({
255
271
  decorationType: 'widget',
256
272
  diffId: diffId,
@@ -1,45 +1,61 @@
1
+ import _typeof from "@babel/runtime/helpers/typeof";
1
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
6
  /**
6
- * Shared prefix for every decoration key produced by the show-diff plugin.
7
- * All keys derive from this, so the full set of plugin decorations can be
8
- * identified by this single prefix.
7
+ * Decoration families produced by the show-diff plugin.
8
+ * Each family owns its own key space and spec shape.
9
9
  */
10
- var DIFF_DECORATION_FAMILY = 'diff';
10
+ export var DecorationFamily = {
11
+ diff: 'diff',
12
+ anchor: 'anchor'
13
+ };
14
+ export var AnchorTypeKey = {
15
+ from: 'from',
16
+ to: 'to',
17
+ left: 'left',
18
+ docMargin: 'doc-margin'
19
+ };
11
20
  /**
12
- * The kinds of decoration the show-diff plugin produces. Each value is the
13
- * leading segment of the generated key, so a decoration's kind can be matched
14
- * with `key?.startsWith(DiffDecorationKey.inline)` etc.
21
+ * The diff-decoration kinds produced by the show-diff plugin. Each value is
22
+ * the leading segment of the generated key, so a diff decoration's kind can be
23
+ * matched with `key?.startsWith(DiffDecorationKey.inline)` etc.
15
24
  */
16
25
  export var DiffDecorationKey = {
17
- inline: "".concat(DIFF_DECORATION_FAMILY, "-inline"),
18
- block: "".concat(DIFF_DECORATION_FAMILY, "-block"),
19
- widget: "".concat(DIFF_DECORATION_FAMILY, "-widget")
26
+ inline: "".concat(DecorationFamily.diff, "-inline"),
27
+ block: "".concat(DecorationFamily.diff, "-block"),
28
+ widget: "".concat(DecorationFamily.diff, "-widget")
29
+ };
30
+ export var AnchorDocMarginKey = "".concat(DecorationFamily.anchor, "-").concat(AnchorTypeKey.docMargin);
31
+ export var buildAnchorDecorationKey = function buildAnchorDecorationKey(_ref) {
32
+ var diffId = _ref.diffId,
33
+ anchorType = _ref.anchorType;
34
+ return "".concat(DecorationFamily.anchor, "-").concat(diffId).concat(anchorType ? "-".concat(anchorType) : '');
20
35
  };
21
36
 
22
37
  /**
23
- * Builds a decoration key in the form `{type}-{active|inactive}`
24
- * (e.g. `diff-inline-active`).
38
+ * Builds a diff decoration key. The extended experience includes the `diffId`
39
+ * in the key so independently rendered decorations for the same type remain
40
+ * distinguishable.
25
41
  */
26
- export var buildDiffDecorationKey = function buildDiffDecorationKey(_ref) {
27
- var decorationKeyPrefix = _ref.decorationKeyPrefix,
28
- isActive = _ref.isActive,
29
- diffId = _ref.diffId;
42
+ export var buildDiffDecorationKey = function buildDiffDecorationKey(_ref2) {
43
+ var decorationKeyPrefix = _ref2.decorationKeyPrefix,
44
+ isActive = _ref2.isActive,
45
+ diffId = _ref2.diffId;
30
46
  if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
31
47
  return "".concat(decorationKeyPrefix, "-").concat(diffId, "-").concat(isActive ? 'active' : 'inactive');
32
48
  }
33
49
  return isActive !== undefined ? "".concat(decorationKeyPrefix, "-").concat(isActive ? 'active' : 'inactive') : decorationKeyPrefix;
34
50
  };
35
- export var buildDiffDecorationSpec = function buildDiffDecorationSpec(_ref2) {
36
- var decorationType = _ref2.decorationType,
37
- diffId = _ref2.diffId,
38
- isActive = _ref2.isActive,
39
- nodeName = _ref2.nodeName,
40
- side = _ref2.side;
51
+ export var buildDiffDecorationSpec = function buildDiffDecorationSpec(_ref3) {
52
+ var decorationType = _ref3.decorationType,
53
+ diffId = _ref3.diffId,
54
+ isActive = _ref3.isActive,
55
+ nodeName = _ref3.nodeName,
56
+ side = _ref3.side;
41
57
  return _objectSpread(_objectSpread({
42
- decorationFamily: DIFF_DECORATION_FAMILY,
58
+ decorationFamily: DecorationFamily.diff,
43
59
  decorationType: decorationType,
44
60
  diffId: diffId,
45
61
  key: buildDiffDecorationKey({
@@ -53,11 +69,46 @@ export var buildDiffDecorationSpec = function buildDiffDecorationSpec(_ref2) {
53
69
  side: side
54
70
  } : {});
55
71
  };
72
+ export function buildAnchorDecorationSpec(_ref4) {
73
+ var anchorType = _ref4.anchorType,
74
+ diffId = _ref4.diffId,
75
+ side = _ref4.side;
76
+ if (anchorType === AnchorTypeKey.docMargin) {
77
+ return _objectSpread({
78
+ decorationFamily: DecorationFamily.anchor,
79
+ anchorType: anchorType,
80
+ key: AnchorDocMarginKey
81
+ }, side !== undefined ? {
82
+ side: side
83
+ } : {});
84
+ }
85
+ if (!diffId) {
86
+ throw new Error("diffId is required for anchor type \"".concat(anchorType, "\""));
87
+ }
88
+ return _objectSpread({
89
+ decorationFamily: DecorationFamily.anchor,
90
+ anchorType: anchorType,
91
+ diffId: diffId,
92
+ key: buildAnchorDecorationKey({
93
+ diffId: diffId,
94
+ anchorType: anchorType
95
+ })
96
+ }, side !== undefined ? {
97
+ side: side
98
+ } : {});
99
+ }
100
+ export var isDiffDecorationSpec = function isDiffDecorationSpec(spec) {
101
+ return Boolean(spec && _typeof(spec) === 'object' && 'decorationFamily' in spec && spec.decorationFamily === DecorationFamily.diff);
102
+ };
103
+ export var isAnchorDecorationSpec = function isAnchorDecorationSpec(spec) {
104
+ return Boolean(spec && _typeof(spec) === 'object' && 'decorationFamily' in spec && spec.decorationFamily === DecorationFamily.anchor);
105
+ };
106
+ export var isDiffDecoration = function isDiffDecoration(decoration) {
107
+ return isDiffDecorationSpec(decoration.spec);
108
+ };
56
109
  export var extractDiffDescriptors = function extractDiffDescriptors(decorations) {
57
- return decorations.find(undefined, undefined, function (spec) {
58
- return spec.decorationFamily === 'diff';
59
- }).map(function (_ref3) {
60
- var spec = _ref3.spec;
110
+ return decorations.find(undefined, undefined, isDiffDecorationSpec).filter(isDiffDecoration).map(function (_ref5) {
111
+ var spec = _ref5.spec;
61
112
  return {
62
113
  id: spec.diffId,
63
114
  type: spec.decorationType
@@ -1,5 +1,7 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
- import { DiffDecorationKey } from './decorations/decorationKeys';
2
+ import _typeof from "@babel/runtime/helpers/typeof";
3
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
+ import { DiffDecorationKey, isDiffDecoration, isDiffDecorationSpec } from './decorations/decorationKeys';
3
5
 
4
6
  /**
5
7
  * True if `fragment` contains at least one inline node (text, hardBreak, emoji, mention, etc.).
@@ -38,6 +40,9 @@ export function isInlineDiffDecorationRenderableInDoc(doc, from, to) {
38
40
  function isRangeFullyInside(range1Start, range1End, range2Start, range2End) {
39
41
  return range2Start <= range1Start && range1End <= range2End;
40
42
  }
43
+ function specHasDiffKeyPrefix(spec, keyPrefix) {
44
+ return Boolean(spec && _typeof(spec) === 'object' && 'key' in spec && typeof spec.key === 'string' && spec.key.startsWith(keyPrefix));
45
+ }
41
46
 
42
47
  /**
43
48
  * Gets scrollable decorations from a DecorationSet, filtering out overlapping decorations
@@ -61,43 +66,47 @@ export var getScrollableDecorations = function getScrollableDecorations(set, doc
61
66
  if (!set) {
62
67
  return [];
63
68
  }
69
+ var isBlockDecoration = function isBlockDecoration(decoration) {
70
+ var _decoration$spec$key$, _decoration$spec;
71
+ return expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? isDiffDecoration(decoration) && decoration.spec.decorationType === 'block' : (_decoration$spec$key$ = (_decoration$spec = decoration.spec) === null || _decoration$spec === void 0 || (_decoration$spec = _decoration$spec.key) === null || _decoration$spec === void 0 ? void 0 : _decoration$spec.startsWith(DiffDecorationKey.block)) !== null && _decoration$spec$key$ !== void 0 ? _decoration$spec$key$ : false;
72
+ };
73
+ var isInlineDecoration = function isInlineDecoration(decoration) {
74
+ var _decoration$spec$key$2, _decoration$spec2;
75
+ return expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? isDiffDecoration(decoration) && decoration.spec.decorationType === 'inline' : (_decoration$spec$key$2 = (_decoration$spec2 = decoration.spec) === null || _decoration$spec2 === void 0 || (_decoration$spec2 = _decoration$spec2.key) === null || _decoration$spec2 === void 0 ? void 0 : _decoration$spec2.startsWith(DiffDecorationKey.inline)) !== null && _decoration$spec$key$2 !== void 0 ? _decoration$spec$key$2 : false;
76
+ };
77
+ var isWidgetDecoration = function isWidgetDecoration(decoration) {
78
+ var _decoration$spec$key$3, _decoration$spec3;
79
+ return expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? isDiffDecoration(decoration) && decoration.spec.decorationType === 'widget' : (_decoration$spec$key$3 = (_decoration$spec3 = decoration.spec) === null || _decoration$spec3 === void 0 || (_decoration$spec3 = _decoration$spec3.key) === null || _decoration$spec3 === void 0 ? void 0 : _decoration$spec3.startsWith(DiffDecorationKey.widget)) !== null && _decoration$spec$key$3 !== void 0 ? _decoration$spec$key$3 : false;
80
+ };
64
81
  var seenBlockKeys = new Set();
65
- var allDecorations = set.find(undefined, undefined, function (spec) {
66
- var _spec$key, _spec$key2, _spec$key3;
67
- return ((_spec$key = spec.key) === null || _spec$key === void 0 ? void 0 : _spec$key.startsWith(DiffDecorationKey.inline)) || ((_spec$key2 = spec.key) === null || _spec$key2 === void 0 ? void 0 : _spec$key2.startsWith(DiffDecorationKey.widget)) || ((_spec$key3 = spec.key) === null || _spec$key3 === void 0 ? void 0 : _spec$key3.startsWith(DiffDecorationKey.block));
82
+ var allDecorations = expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? set.find(undefined, undefined, isDiffDecorationSpec) : set.find(undefined, undefined, function (spec) {
83
+ return specHasDiffKeyPrefix(spec, DiffDecorationKey.inline) || specHasDiffKeyPrefix(spec, DiffDecorationKey.widget) || specHasDiffKeyPrefix(spec, DiffDecorationKey.block);
68
84
  });
69
85
 
70
86
  // First pass: filter out listItem blocks and deduplicates blocks
71
87
  var filtered = allDecorations.filter(function (dec) {
72
- var _dec$spec, _dec$spec$nodeName, _dec$spec3;
73
- if ((_dec$spec = dec.spec) !== null && _dec$spec !== void 0 && (_dec$spec = _dec$spec.key) !== null && _dec$spec !== void 0 && _dec$spec.startsWith(DiffDecorationKey.block)) {
74
- var _dec$spec2;
88
+ if (!isBlockDecoration(dec) && !isInlineDecoration(dec) && !isWidgetDecoration(dec)) {
89
+ return false;
90
+ }
91
+ if (isBlockDecoration(dec)) {
92
+ var _dec$spec, _dec$spec$nodeName;
75
93
  // Skip listItem blocks as they are not scrollable
76
- if (((_dec$spec2 = dec.spec) === null || _dec$spec2 === void 0 ? void 0 : _dec$spec2.nodeName) === 'listItem') return false;
94
+ if (((_dec$spec = dec.spec) === null || _dec$spec === void 0 ? void 0 : _dec$spec.nodeName) === 'listItem') return false;
95
+ var key = "".concat(dec.from, "-").concat(dec.to, "-").concat((_dec$spec$nodeName = dec.spec.nodeName) !== null && _dec$spec$nodeName !== void 0 ? _dec$spec$nodeName : '');
96
+ // Skip blocks that have already been seen
97
+ if (seenBlockKeys.has(key)) return false;
98
+ seenBlockKeys.add(key);
77
99
  }
78
- var key = "".concat(dec.from, "-").concat(dec.to, "-").concat((_dec$spec$nodeName = (_dec$spec3 = dec.spec) === null || _dec$spec3 === void 0 ? void 0 : _dec$spec3.nodeName) !== null && _dec$spec$nodeName !== void 0 ? _dec$spec$nodeName : '');
79
- // Skip blocks that have already been seen
80
- if (seenBlockKeys.has(key)) return false;
81
- seenBlockKeys.add(key);
82
100
  return true;
83
101
  });
84
102
 
85
103
  // Separate decorations by type for easier processing
86
- var blocks = filtered.filter(function (d) {
87
- var _d$spec;
88
- return (_d$spec = d.spec) === null || _d$spec === void 0 || (_d$spec = _d$spec.key) === null || _d$spec === void 0 ? void 0 : _d$spec.startsWith(DiffDecorationKey.block);
89
- });
90
- var rawInlines = filtered.filter(function (d) {
91
- var _d$spec2;
92
- return (_d$spec2 = d.spec) === null || _d$spec2 === void 0 || (_d$spec2 = _d$spec2.key) === null || _d$spec2 === void 0 ? void 0 : _d$spec2.startsWith(DiffDecorationKey.inline);
93
- });
104
+ var blocks = filtered.filter(isBlockDecoration);
105
+ var rawInlines = filtered.filter(isInlineDecoration);
94
106
  var inlines = doc !== undefined ? rawInlines.filter(function (d) {
95
107
  return isInlineDiffDecorationRenderableInDoc(doc, d.from, d.to);
96
108
  }) : rawInlines;
97
- var widgets = filtered.filter(function (d) {
98
- var _d$spec3;
99
- return (_d$spec3 = d.spec) === null || _d$spec3 === void 0 || (_d$spec3 = _d$spec3.key) === null || _d$spec3 === void 0 ? void 0 : _d$spec3.startsWith(DiffDecorationKey.widget);
100
- });
109
+ var widgets = filtered.filter(isWidgetDecoration);
101
110
 
102
111
  // Second pass: exclude overlapping decorations
103
112
  // Rules:
@@ -35,6 +35,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
35
35
  isInverted: false,
36
36
  diffType: 'inline',
37
37
  hideDeletedDiffs: false,
38
+ showIndicators: false,
38
39
  diffDescriptors: []
39
40
  } : {});
40
41
  },
@@ -43,7 +44,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
43
44
  var newPluginState = currentPluginState;
44
45
  if (meta) {
45
46
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
46
- var _newPluginState, _newPluginState2, _newPluginState3;
47
+ var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4;
47
48
  // Update the plugin state with the new metadata
48
49
  newPluginState = _objectSpread(_objectSpread(_objectSpread({}, currentPluginState), meta), {}, {
49
50
  isDisplayingChanges: true,
@@ -61,7 +62,8 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
61
62
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
62
63
  isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted,
63
64
  diffType: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.diffType,
64
- hideDeletedDiffs: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.hideDeletedDiffs
65
+ hideDeletedDiffs: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.hideDeletedDiffs,
66
+ showIndicators: (_newPluginState4 = newPluginState) === null || _newPluginState4 === void 0 ? void 0 : _newPluginState4.showIndicators
65
67
  } : {})),
66
68
  decorations = _calculateDiffDecorat.decorations,
67
69
  diffDescriptors = _calculateDiffDecorat.diffDescriptors;
@@ -120,7 +122,8 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
120
122
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
121
123
  isInverted: newPluginState.isInverted,
122
124
  diffType: newPluginState.diffType,
123
- hideDeletedDiffs: newPluginState.hideDeletedDiffs
125
+ hideDeletedDiffs: newPluginState.hideDeletedDiffs,
126
+ showIndicators: newPluginState.showIndicators
124
127
  } : {})),
125
128
  updatedDecorations = _calculateDiffDecorat2.decorations,
126
129
  updatedDiffDescriptors = _calculateDiffDecorat2.diffDescriptors;
@@ -160,10 +163,9 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
160
163
 
161
164
  // Scroll to the first decoration when scrollIntoView was requested
162
165
  if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
163
- var _cancelPendingScrollT, _pluginState$decorati;
166
+ var _cancelPendingScrollT;
164
167
  (_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 || _cancelPendingScrollT();
165
- var allDecorations = ((_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
166
- cancelPendingScrollToDecoration = scrollToFirstDecoration(view, allDecorations);
168
+ cancelPendingScrollToDecoration = scrollToFirstDecoration(view, pluginState.decorations);
167
169
 
168
170
  // Reset the flag so we don't scroll again on subsequent updates
169
171
  view.dispatch(view.state.tr.setMeta(showDiffPluginKey, {
@@ -1,4 +1,4 @@
1
- import { DiffDecorationKey } from './decorations/decorationKeys';
1
+ import { isDiffDecoration, isDiffDecorationSpec } from './decorations/decorationKeys';
2
2
 
3
3
  /**
4
4
  * Extra space above the scrolled-to element so it does not sit flush under the
@@ -41,16 +41,16 @@ function scrollToSelection(node) {
41
41
  *
42
42
  * @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
43
43
  */
44
- export var scrollToFirstDecoration = function scrollToFirstDecoration(view, decorations) {
45
- var decoration = decorations[0];
44
+ export var scrollToFirstDecoration = function scrollToFirstDecoration(view, set) {
45
+ var decoration = set.find(undefined, undefined, isDiffDecorationSpec).find(isDiffDecoration);
46
46
  if (!decoration) {
47
47
  return function () {};
48
48
  }
49
49
  var rafId = requestAnimationFrame(function () {
50
- var _decoration$spec, _decoration$type;
50
+ var _decoration$type;
51
51
  rafId = null;
52
52
  // @ts-expect-error - decoration.type is not typed public API
53
- if ((_decoration$spec = decoration.spec) !== null && _decoration$spec !== void 0 && (_decoration$spec = _decoration$spec.key) !== null && _decoration$spec !== void 0 && _decoration$spec.startsWith(DiffDecorationKey.widget) && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
53
+ if (decoration.spec.decorationType === 'widget' && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
54
54
  // @ts-expect-error - decoration.type is not typed public API
55
55
  var widgetDom = decoration.type.toDOM;
56
56
  // Always scroll to the top of this decoration even if it's in view already
@@ -84,9 +84,8 @@ export var scrollToActiveDecoration = function scrollToActiveDecoration(view, de
84
84
  return function () {};
85
85
  }
86
86
  var rafId = requestAnimationFrame(function () {
87
- var _decoration$spec2;
88
87
  rafId = null;
89
- if ((_decoration$spec2 = decoration.spec) !== null && _decoration$spec2 !== void 0 && (_decoration$spec2 = _decoration$spec2.key) !== null && _decoration$spec2 !== void 0 && _decoration$spec2.startsWith(DiffDecorationKey.widget)) {
88
+ if (isDiffDecoration(decoration) && decoration.spec.decorationType === 'widget') {
90
89
  var _decoration$type2;
91
90
  // @ts-expect-error - decoration.type is not typed public API
92
91
  var widgetDom = decoration === null || decoration === void 0 || (_decoration$type2 = decoration.type) === null || _decoration$type2 === void 0 ? void 0 : _decoration$type2.toDOM;
@@ -1,9 +1,11 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
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
+ import React from 'react';
4
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
6
  import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
6
7
  import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
8
+ import { IndicatorBarContentComponent } from './ui/IndicatorBar/IndicatorBarContentComponent';
7
9
  export var showDiffPlugin = function showDiffPlugin(_ref) {
8
10
  var api = _ref.api,
9
11
  config = _ref.config;
@@ -59,6 +61,14 @@ export var showDiffPlugin = function showDiffPlugin(_ref) {
59
61
  }
60
62
  }];
61
63
  },
64
+ contentComponent: function contentComponent() {
65
+ if (!expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
66
+ return null;
67
+ }
68
+ return /*#__PURE__*/React.createElement(IndicatorBarContentComponent, {
69
+ api: api
70
+ });
71
+ },
62
72
  getSharedState: function getSharedState(editorState) {
63
73
  if (!editorState) {
64
74
  return _objectSpread({
@@ -75,7 +85,8 @@ export var showDiffPlugin = function showDiffPlugin(_ref) {
75
85
  activeIndex: pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex,
76
86
  numberOfChanges: decorationCount.length
77
87
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
78
- diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors
88
+ diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors,
89
+ showIndicators: pluginState === null || pluginState === void 0 ? void 0 : pluginState.showIndicators
79
90
  } : {});
80
91
  }
81
92
  };