@atlaskit/editor-plugin-show-diff 10.0.1 → 10.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.
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
@@ -7,6 +7,8 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.getScrollableDecorations = void 0;
8
8
  exports.isInlineDiffDecorationRenderableInDoc = isInlineDiffDecorationRenderableInDoc;
9
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
11
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
10
12
  var _decorationKeys = require("./decorations/decorationKeys");
11
13
  /**
12
14
  * True if `fragment` contains at least one inline node (text, hardBreak, emoji, mention, etc.).
@@ -45,6 +47,9 @@ function isInlineDiffDecorationRenderableInDoc(doc, from, to) {
45
47
  function isRangeFullyInside(range1Start, range1End, range2Start, range2End) {
46
48
  return range2Start <= range1Start && range1End <= range2End;
47
49
  }
50
+ function specHasDiffKeyPrefix(spec, keyPrefix) {
51
+ return Boolean(spec && (0, _typeof2.default)(spec) === 'object' && 'key' in spec && typeof spec.key === 'string' && spec.key.startsWith(keyPrefix));
52
+ }
48
53
 
49
54
  /**
50
55
  * Gets scrollable decorations from a DecorationSet, filtering out overlapping decorations
@@ -68,43 +73,47 @@ var getScrollableDecorations = exports.getScrollableDecorations = function getSc
68
73
  if (!set) {
69
74
  return [];
70
75
  }
76
+ var isBlockDecoration = function isBlockDecoration(decoration) {
77
+ var _decoration$spec$key$, _decoration$spec;
78
+ return (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? (0, _decorationKeys.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(_decorationKeys.DiffDecorationKey.block)) !== null && _decoration$spec$key$ !== void 0 ? _decoration$spec$key$ : false;
79
+ };
80
+ var isInlineDecoration = function isInlineDecoration(decoration) {
81
+ var _decoration$spec$key$2, _decoration$spec2;
82
+ return (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? (0, _decorationKeys.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(_decorationKeys.DiffDecorationKey.inline)) !== null && _decoration$spec$key$2 !== void 0 ? _decoration$spec$key$2 : false;
83
+ };
84
+ var isWidgetDecoration = function isWidgetDecoration(decoration) {
85
+ var _decoration$spec$key$3, _decoration$spec3;
86
+ return (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? (0, _decorationKeys.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(_decorationKeys.DiffDecorationKey.widget)) !== null && _decoration$spec$key$3 !== void 0 ? _decoration$spec$key$3 : false;
87
+ };
71
88
  var seenBlockKeys = new Set();
72
- var allDecorations = set.find(undefined, undefined, function (spec) {
73
- var _spec$key, _spec$key2, _spec$key3;
74
- return ((_spec$key = spec.key) === null || _spec$key === void 0 ? void 0 : _spec$key.startsWith(_decorationKeys.DiffDecorationKey.inline)) || ((_spec$key2 = spec.key) === null || _spec$key2 === void 0 ? void 0 : _spec$key2.startsWith(_decorationKeys.DiffDecorationKey.widget)) || ((_spec$key3 = spec.key) === null || _spec$key3 === void 0 ? void 0 : _spec$key3.startsWith(_decorationKeys.DiffDecorationKey.block));
89
+ var allDecorations = (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? set.find(undefined, undefined, _decorationKeys.isDiffDecorationSpec) : set.find(undefined, undefined, function (spec) {
90
+ return specHasDiffKeyPrefix(spec, _decorationKeys.DiffDecorationKey.inline) || specHasDiffKeyPrefix(spec, _decorationKeys.DiffDecorationKey.widget) || specHasDiffKeyPrefix(spec, _decorationKeys.DiffDecorationKey.block);
75
91
  });
76
92
 
77
93
  // First pass: filter out listItem blocks and deduplicates blocks
78
94
  var filtered = allDecorations.filter(function (dec) {
79
- var _dec$spec, _dec$spec$nodeName, _dec$spec3;
80
- if ((_dec$spec = dec.spec) !== null && _dec$spec !== void 0 && (_dec$spec = _dec$spec.key) !== null && _dec$spec !== void 0 && _dec$spec.startsWith(_decorationKeys.DiffDecorationKey.block)) {
81
- var _dec$spec2;
95
+ if (!isBlockDecoration(dec) && !isInlineDecoration(dec) && !isWidgetDecoration(dec)) {
96
+ return false;
97
+ }
98
+ if (isBlockDecoration(dec)) {
99
+ var _dec$spec, _dec$spec$nodeName;
82
100
  // Skip listItem blocks as they are not scrollable
83
- if (((_dec$spec2 = dec.spec) === null || _dec$spec2 === void 0 ? void 0 : _dec$spec2.nodeName) === 'listItem') return false;
101
+ if (((_dec$spec = dec.spec) === null || _dec$spec === void 0 ? void 0 : _dec$spec.nodeName) === 'listItem') return false;
102
+ var key = "".concat(dec.from, "-").concat(dec.to, "-").concat((_dec$spec$nodeName = dec.spec.nodeName) !== null && _dec$spec$nodeName !== void 0 ? _dec$spec$nodeName : '');
103
+ // Skip blocks that have already been seen
104
+ if (seenBlockKeys.has(key)) return false;
105
+ seenBlockKeys.add(key);
84
106
  }
85
- 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 : '');
86
- // Skip blocks that have already been seen
87
- if (seenBlockKeys.has(key)) return false;
88
- seenBlockKeys.add(key);
89
107
  return true;
90
108
  });
91
109
 
92
110
  // Separate decorations by type for easier processing
93
- var blocks = filtered.filter(function (d) {
94
- var _d$spec;
95
- 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(_decorationKeys.DiffDecorationKey.block);
96
- });
97
- var rawInlines = filtered.filter(function (d) {
98
- var _d$spec2;
99
- 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(_decorationKeys.DiffDecorationKey.inline);
100
- });
111
+ var blocks = filtered.filter(isBlockDecoration);
112
+ var rawInlines = filtered.filter(isInlineDecoration);
101
113
  var inlines = doc !== undefined ? rawInlines.filter(function (d) {
102
114
  return isInlineDiffDecorationRenderableInDoc(doc, d.from, d.to);
103
115
  }) : rawInlines;
104
- var widgets = filtered.filter(function (d) {
105
- var _d$spec3;
106
- 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(_decorationKeys.DiffDecorationKey.widget);
107
- });
116
+ var widgets = filtered.filter(isWidgetDecoration);
108
117
 
109
118
  // Second pass: exclude overlapping decorations
110
119
  // Rules:
@@ -42,6 +42,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
42
42
  isInverted: false,
43
43
  diffType: 'inline',
44
44
  hideDeletedDiffs: false,
45
+ showIndicators: false,
45
46
  diffDescriptors: []
46
47
  } : {});
47
48
  },
@@ -50,7 +51,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
50
51
  var newPluginState = currentPluginState;
51
52
  if (meta) {
52
53
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
53
- var _newPluginState, _newPluginState2, _newPluginState3;
54
+ var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4;
54
55
  // Update the plugin state with the new metadata
55
56
  newPluginState = _objectSpread(_objectSpread(_objectSpread({}, currentPluginState), meta), {}, {
56
57
  isDisplayingChanges: true,
@@ -68,7 +69,8 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
68
69
  }, (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
69
70
  isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted,
70
71
  diffType: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.diffType,
71
- hideDeletedDiffs: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.hideDeletedDiffs
72
+ hideDeletedDiffs: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.hideDeletedDiffs,
73
+ showIndicators: (_newPluginState4 = newPluginState) === null || _newPluginState4 === void 0 ? void 0 : _newPluginState4.showIndicators
72
74
  } : {})),
73
75
  decorations = _calculateDiffDecorat.decorations,
74
76
  diffDescriptors = _calculateDiffDecorat.diffDescriptors;
@@ -127,7 +129,8 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
127
129
  }, (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
128
130
  isInverted: newPluginState.isInverted,
129
131
  diffType: newPluginState.diffType,
130
- hideDeletedDiffs: newPluginState.hideDeletedDiffs
132
+ hideDeletedDiffs: newPluginState.hideDeletedDiffs,
133
+ showIndicators: newPluginState.showIndicators
131
134
  } : {})),
132
135
  updatedDecorations = _calculateDiffDecorat2.decorations,
133
136
  updatedDiffDescriptors = _calculateDiffDecorat2.diffDescriptors;
@@ -167,10 +170,9 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
167
170
 
168
171
  // Scroll to the first decoration when scrollIntoView was requested
169
172
  if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView && (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
170
- var _cancelPendingScrollT, _pluginState$decorati;
173
+ var _cancelPendingScrollT;
171
174
  (_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 || _cancelPendingScrollT();
172
- var allDecorations = ((_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
173
- cancelPendingScrollToDecoration = (0, _scrollToDiff.scrollToFirstDecoration)(view, allDecorations);
175
+ cancelPendingScrollToDecoration = (0, _scrollToDiff.scrollToFirstDecoration)(view, pluginState.decorations);
174
176
 
175
177
  // Reset the flag so we don't scroll again on subsequent updates
176
178
  view.dispatch(view.state.tr.setMeta(showDiffPluginKey, {
@@ -46,16 +46,16 @@ function scrollToSelection(node) {
46
46
  *
47
47
  * @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
48
48
  */
49
- var scrollToFirstDecoration = exports.scrollToFirstDecoration = function scrollToFirstDecoration(view, decorations) {
50
- var decoration = decorations[0];
49
+ var scrollToFirstDecoration = exports.scrollToFirstDecoration = function scrollToFirstDecoration(view, set) {
50
+ var decoration = set.find(undefined, undefined, _decorationKeys.isDiffDecorationSpec).find(_decorationKeys.isDiffDecoration);
51
51
  if (!decoration) {
52
52
  return function () {};
53
53
  }
54
54
  var rafId = requestAnimationFrame(function () {
55
- var _decoration$spec, _decoration$type;
55
+ var _decoration$type;
56
56
  rafId = null;
57
57
  // @ts-expect-error - decoration.type is not typed public API
58
- if ((_decoration$spec = decoration.spec) !== null && _decoration$spec !== void 0 && (_decoration$spec = _decoration$spec.key) !== null && _decoration$spec !== void 0 && _decoration$spec.startsWith(_decorationKeys.DiffDecorationKey.widget) && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
58
+ if (decoration.spec.decorationType === 'widget' && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
59
59
  // @ts-expect-error - decoration.type is not typed public API
60
60
  var widgetDom = decoration.type.toDOM;
61
61
  // Always scroll to the top of this decoration even if it's in view already
@@ -89,9 +89,8 @@ var scrollToActiveDecoration = exports.scrollToActiveDecoration = function scrol
89
89
  return function () {};
90
90
  }
91
91
  var rafId = requestAnimationFrame(function () {
92
- var _decoration$spec2;
93
92
  rafId = null;
94
- if ((_decoration$spec2 = decoration.spec) !== null && _decoration$spec2 !== void 0 && (_decoration$spec2 = _decoration$spec2.key) !== null && _decoration$spec2 !== void 0 && _decoration$spec2.startsWith(_decorationKeys.DiffDecorationKey.widget)) {
93
+ if ((0, _decorationKeys.isDiffDecoration)(decoration) && decoration.spec.decorationType === 'widget') {
95
94
  var _decoration$type2;
96
95
  // @ts-expect-error - decoration.type is not typed public API
97
96
  var widgetDom = decoration === null || decoration === void 0 || (_decoration$type2 = decoration.type) === null || _decoration$type2 === void 0 ? void 0 : _decoration$type2.toDOM;
@@ -6,9 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.showDiffPlugin = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _react = _interopRequireDefault(require("react"));
9
10
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
10
11
  var _getScrollableDecorations = require("./pm-plugins/getScrollableDecorations");
11
12
  var _main = require("./pm-plugins/main");
13
+ var _IndicatorBarContentComponent = require("./ui/IndicatorBar/IndicatorBarContentComponent");
12
14
  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; }
13
15
  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; }
14
16
  var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
@@ -66,6 +68,14 @@ var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
66
68
  }
67
69
  }];
68
70
  },
71
+ contentComponent: function contentComponent() {
72
+ if (!(0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
73
+ return null;
74
+ }
75
+ return /*#__PURE__*/_react.default.createElement(_IndicatorBarContentComponent.IndicatorBarContentComponent, {
76
+ api: api
77
+ });
78
+ },
69
79
  getSharedState: function getSharedState(editorState) {
70
80
  if (!editorState) {
71
81
  return _objectSpread({
@@ -82,7 +92,8 @@ var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
82
92
  activeIndex: pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex,
83
93
  numberOfChanges: decorationCount.length
84
94
  }, (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
85
- diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors
95
+ diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors,
96
+ showIndicators: pluginState === null || pluginState === void 0 ? void 0 : pluginState.showIndicators
86
97
  } : {});
87
98
  }
88
99
  };
@@ -0,0 +1,9 @@
1
+
2
+ ._2rko1rr0{border-radius:var(--ds-radius-full,9999px)}._17c61i8t{position-visibility:anchors-valid}
3
+ ._18u0mgjw{margin-left:var(--ds-space-negative-200,-1pc)}
4
+ ._19pk196n{margin-top:var(--ds-space-negative-075,-6px)}
5
+ ._1bsb1l7b{width:3px}
6
+ ._bfhkvbh5{background-color:var(--ds-border-information,#357de8)}
7
+ ._kqswstnw{position:absolute}
8
+ ._lcxvglyw{pointer-events:none}
9
+ ._otyr196n{margin-bottom:var(--ds-space-negative-075,-6px)}
@@ -0,0 +1,33 @@
1
+ /* IndicatorBar.tsx generated by @compiled/babel-plugin v0.39.1 */
2
+ "use strict";
3
+
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.IndicatorBar = IndicatorBar;
9
+ require("./IndicatorBar.compiled.css");
10
+ var React = _interopRequireWildcard(require("react"));
11
+ var _runtime = require("@compiled/react/runtime");
12
+ var _decorationKeys = require("../../pm-plugins/decorations/decorationKeys");
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
14
+ var barStyles = null;
15
+ function IndicatorBar(_ref) {
16
+ var anchorTop = _ref.anchorTop,
17
+ anchorBottom = _ref.anchorBottom,
18
+ anchorLeft = _ref.anchorLeft,
19
+ anchorLeftFallback = _ref.anchorLeftFallback;
20
+ var leftAnchors = [anchorLeft, anchorLeftFallback, _decorationKeys.AnchorDocMarginKey].filter(Boolean).map(function (anchor) {
21
+ return "anchor(--".concat(anchor, " left)");
22
+ }).join(', ');
23
+ return /*#__PURE__*/React.createElement("span", {
24
+ "data-testid": "diff-indicator-bar",
25
+ style: {
26
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values
27
+ left: "min(".concat(leftAnchors, ")"),
28
+ top: "anchor(--".concat(anchorTop, " top)"),
29
+ bottom: "anchor(--".concat(anchorBottom, " bottom)")
30
+ },
31
+ className: (0, _runtime.ax)(["_2rko1rr0 _kqswstnw _1bsb1l7b _bfhkvbh5 _lcxvglyw _18u0mgjw _17c61i8t _19pk196n _otyr196n"])
32
+ });
33
+ }
@@ -0,0 +1,87 @@
1
+ /* IndicatorBarContentComponent.tsx generated by @compiled/babel-plugin v0.39.1 */
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.IndicatorBarContentComponent = void 0;
9
+ var _runtime = require("@compiled/react/runtime");
10
+ var _react = _interopRequireDefault(require("react"));
11
+ var _hooks = require("@atlaskit/editor-common/hooks");
12
+ var _decorationKeys = require("../../pm-plugins/decorations/decorationKeys");
13
+ var _IndicatorBar = require("./IndicatorBar");
14
+ var renderIndicatorBar = function renderIndicatorBar(descriptor) {
15
+ switch (descriptor.type) {
16
+ case 'inline':
17
+ {
18
+ return /*#__PURE__*/_react.default.createElement(_IndicatorBar.IndicatorBar, {
19
+ key: descriptor.id,
20
+ anchorTop: (0, _decorationKeys.buildAnchorDecorationKey)({
21
+ diffId: descriptor.id,
22
+ anchorType: _decorationKeys.AnchorTypeKey.from
23
+ }),
24
+ anchorBottom: (0, _decorationKeys.buildAnchorDecorationKey)({
25
+ diffId: descriptor.id,
26
+ anchorType: _decorationKeys.AnchorTypeKey.to
27
+ }),
28
+ anchorLeft: (0, _decorationKeys.buildAnchorDecorationKey)({
29
+ diffId: descriptor.id,
30
+ anchorType: _decorationKeys.AnchorTypeKey.left
31
+ })
32
+ });
33
+ }
34
+ case 'widget':
35
+ {
36
+ return /*#__PURE__*/_react.default.createElement(_IndicatorBar.IndicatorBar, {
37
+ key: descriptor.id,
38
+ anchorTop: (0, _decorationKeys.buildAnchorDecorationKey)({
39
+ diffId: descriptor.id
40
+ }),
41
+ anchorBottom: (0, _decorationKeys.buildAnchorDecorationKey)({
42
+ diffId: descriptor.id
43
+ }),
44
+ anchorLeft: (0, _decorationKeys.buildAnchorDecorationKey)({
45
+ diffId: descriptor.id,
46
+ anchorType: _decorationKeys.AnchorTypeKey.left
47
+ }),
48
+ anchorLeftFallback: (0, _decorationKeys.buildAnchorDecorationKey)({
49
+ diffId: descriptor.id
50
+ })
51
+ });
52
+ }
53
+ /**
54
+ * TODO EDITOR-7711:
55
+ * Support IndicatorBar for block-changed type diffs.
56
+ */
57
+ default:
58
+ return null;
59
+ }
60
+ };
61
+
62
+ /**
63
+ * Renders IndicatorBar elements for each diff ID in the current plugin state.
64
+ *
65
+ * This is rendered as a contentComponent so that the IndicatorBar elements
66
+ * share the same DOM context as their CSS anchor spans, allowing the browser
67
+ * to resolve anchor-name references correctly.
68
+ */
69
+
70
+ var IndicatorBarContentComponent = exports.IndicatorBarContentComponent = function IndicatorBarContentComponent(_ref) {
71
+ var api = _ref.api;
72
+ var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['showDiff'], function (state) {
73
+ var _state$showDiffState, _state$showDiffState2, _state$showDiffState3;
74
+ return {
75
+ showIndicators: (_state$showDiffState = state.showDiffState) === null || _state$showDiffState === void 0 ? void 0 : _state$showDiffState.showIndicators,
76
+ isDisplayingChanges: (_state$showDiffState2 = state.showDiffState) === null || _state$showDiffState2 === void 0 ? void 0 : _state$showDiffState2.isDisplayingChanges,
77
+ diffDescriptors: (_state$showDiffState3 = state.showDiffState) === null || _state$showDiffState3 === void 0 ? void 0 : _state$showDiffState3.diffDescriptors
78
+ };
79
+ }),
80
+ showIndicators = _useSharedPluginState.showIndicators,
81
+ isDisplayingChanges = _useSharedPluginState.isDisplayingChanges,
82
+ diffDescriptors = _useSharedPluginState.diffDescriptors;
83
+ if (!showIndicators || !isDisplayingChanges || !(diffDescriptors !== null && diffDescriptors !== void 0 && diffDescriptors.length)) {
84
+ return null;
85
+ }
86
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, diffDescriptors.map(renderIndicatorBar));
87
+ };
@@ -6,6 +6,7 @@ import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document
6
6
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
8
  import { areDocsEqualByBlockStructureAndText } from '../areDocsEqualByBlockStructureAndText';
9
+ import { createDocMarginAnchorWidget } from '../decorations/createAnchorDecorationWidgets';
9
10
  import { createBlockChangedDecoration } from '../decorations/createBlockChangedDecoration';
10
11
  import { createInlineChangedDecoration } from '../decorations/createInlineChangedDecoration';
11
12
  import { createNodeChangedDecorationWidget } from '../decorations/createNodeChangedDecorationWidget';
@@ -77,13 +78,15 @@ const calculateDiffDecorationsInner = ({
77
78
  api,
78
79
  isInverted = false,
79
80
  diffType = 'inline',
80
- hideDeletedDiffs = false
81
+ hideDeletedDiffs = false,
82
+ showIndicators = false
81
83
  }) => {
82
84
  const {
83
85
  originalDoc,
84
- steps
86
+ steps,
87
+ isDisplayingChanges
85
88
  } = pluginState;
86
- if (!originalDoc || !pluginState.isDisplayingChanges) {
89
+ if (!originalDoc || !isDisplayingChanges) {
87
90
  return {
88
91
  decorations: DecorationSet.empty,
89
92
  diffDescriptors: []
@@ -139,6 +142,13 @@ const calculateDiffDecorationsInner = ({
139
142
  steps
140
143
  });
141
144
  const decorations = [];
145
+
146
+ /**
147
+ * If showIndicators is on, we create an anchor widget here to mark the doc margin.
148
+ */
149
+ if (showIndicators && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
150
+ decorations.push(createDocMarginAnchorWidget());
151
+ }
142
152
  changes.forEach(change => {
143
153
  const isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
144
154
  // Our default operations are insertions, so it should match the opposite of isInverted.
@@ -147,11 +157,13 @@ const calculateDiffDecorationsInner = ({
147
157
  const shouldHideDeleted = expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? isInverted && hideDeletedDiffs : false;
148
158
  decorations.push(...createInlineChangedDecoration({
149
159
  change,
160
+ doc: tr.doc,
150
161
  colorScheme,
151
162
  isActive,
152
163
  ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) && {
153
164
  isInserted,
154
- shouldHideDeleted
165
+ shouldHideDeleted,
166
+ showIndicators
155
167
  })
156
168
  }));
157
169
  decorations.push(...calculateNodesForBlockDecoration({
@@ -181,7 +193,8 @@ const calculateDiffDecorationsInner = ({
181
193
  ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) && {
182
194
  isInserted: !isInserted,
183
195
  diffType
184
- })
196
+ }),
197
+ showIndicators
185
198
  }));
186
199
  }
187
200
  }
@@ -233,7 +246,8 @@ export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner
233
246
  activeIndexPos,
234
247
  isInverted,
235
248
  diffType,
236
- hideDeletedDiffs
249
+ hideDeletedDiffs,
250
+ showIndicators
237
251
  }], [{
238
252
  pluginState: lastPluginState,
239
253
  state: lastState,
@@ -242,13 +256,14 @@ export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner
242
256
  activeIndexPos: lastActiveIndexPos,
243
257
  isInverted: lastIsInverted,
244
258
  diffType: lastDiffType,
245
- hideDeletedDiffs: lastHideDeletedDiffs
259
+ hideDeletedDiffs: lastHideDeletedDiffs,
260
+ showIndicators: lastShowIndicators
246
261
  }]) => {
247
262
  var _ref2;
248
263
  const originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
249
264
  if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
250
265
  var _ref;
251
- return (_ref = 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) !== null && _ref !== void 0 ? _ref : false;
266
+ return (_ref = 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 && showIndicators === lastShowIndicators) !== null && _ref !== void 0 ? _ref : false;
252
267
  }
253
268
  return (_ref2 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref2 !== void 0 ? _ref2 : false;
254
269
  });
@@ -0,0 +1,205 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ import { buildAnchorDecorationKey, buildAnchorDecorationSpec, AnchorDocMarginKey, AnchorTypeKey } from './decorationKeys';
3
+ const SIDE = 1;
4
+ const findPosAfterLastChild = (node, nodeStart) => {
5
+ if (!node) {
6
+ return undefined;
7
+ }
8
+ const lastChild = node.lastChild;
9
+ if (!lastChild) {
10
+ return undefined;
11
+ }
12
+ const 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
+ const edgeCases = (doc, from) => {
22
+ const $from = doc.resolve(from);
23
+ const 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
+ const lastRow = docLevelNode.lastChild;
36
+ if (!lastRow) {
37
+ return undefined;
38
+ }
39
+ const lastRowStart = $from.start(1) + docLevelNode.content.size - lastRow.nodeSize;
40
+ const firstCellOfLastRow = lastRow.firstChild;
41
+ const 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
+ const 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
+ const firstLayoutColumn = docLevelNode.firstChild;
71
+ const 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 const createDocMarginAnchorWidget = () => {
92
+ return Decoration.widget(0, () => {
93
+ const span = document.createElement('span');
94
+ span.style.setProperty('anchor-name', `--${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 const createLeftAnchorWidget = ({
113
+ doc,
114
+ from,
115
+ diffId
116
+ }) => {
117
+ const edgeCase = edgeCases(doc, from);
118
+ if (edgeCase === undefined) {
119
+ return undefined;
120
+ }
121
+ const leftAnchorKey = buildAnchorDecorationKey({
122
+ diffId,
123
+ anchorType: AnchorTypeKey.left
124
+ });
125
+ return Decoration.widget(edgeCase.pos, () => {
126
+ const span = document.createElement('span');
127
+ span.style.setProperty('anchor-name', `--${leftAnchorKey}`);
128
+ span.style.setProperty('position', 'absolute');
129
+ span.style.setProperty('left', edgeCase.leftMargin);
130
+ return span;
131
+ }, buildAnchorDecorationSpec({
132
+ diffId,
133
+ anchorType: AnchorTypeKey.left,
134
+ side: edgeCase.side * SIDE
135
+ }));
136
+ };
137
+ const isFullNodeRange = (doc, from, to) => {
138
+ let matchesFullNodeRange = false;
139
+ doc.nodesBetween(from, to, (node, pos) => {
140
+ if (pos === from && pos + node.nodeSize === to) {
141
+ matchesFullNodeRange = true;
142
+ return false;
143
+ }
144
+ return true;
145
+ });
146
+ return matchesFullNodeRange;
147
+ };
148
+ /**
149
+ * Creates invisible anchor widgets for a single inline diff range so that the
150
+ * `IndicatorBar` can use CSS anchor positioning to align itself with the diff.
151
+ *
152
+ * - A `from` anchor is placed at the start of the range (top of the bar).
153
+ * - A `to` anchor is placed at the end of the range (bottom of the bar).
154
+ * - An optional `left` anchor is placed before the first textblock when the
155
+ * diff is inside a resizable block node (table, layout, expand).
156
+ */
157
+ export const createInlineIndicatorAnchorWidgets = ({
158
+ doc,
159
+ from,
160
+ to,
161
+ diffId
162
+ }) => {
163
+ if (isFullNodeRange(doc, from, to)) {
164
+ return [];
165
+ }
166
+ const leftAnchor = createLeftAnchorWidget({
167
+ doc,
168
+ from,
169
+ diffId
170
+ });
171
+ const maybeLeftAnchor = leftAnchor ? [leftAnchor] : [];
172
+
173
+ /**
174
+ * Two widgets mark the start and end of the inline range so the
175
+ * IndicatorBar can determine top/bottom even when the decoration
176
+ * spans multiple blocks.
177
+ */
178
+ const fromAnchorKey = buildAnchorDecorationKey({
179
+ diffId,
180
+ anchorType: AnchorTypeKey.from
181
+ });
182
+ const fromWidget = Decoration.widget(from, () => {
183
+ const span = document.createElement('span');
184
+ span.style.setProperty('anchor-name', `--${fromAnchorKey}`);
185
+ return span;
186
+ }, buildAnchorDecorationSpec({
187
+ diffId,
188
+ anchorType: AnchorTypeKey.from,
189
+ side: 1
190
+ }));
191
+ const toAnchorKey = buildAnchorDecorationKey({
192
+ diffId,
193
+ anchorType: AnchorTypeKey.to
194
+ });
195
+ const toWidget = Decoration.widget(to, () => {
196
+ const span = document.createElement('span');
197
+ span.style.setProperty('anchor-name', `--${toAnchorKey}`);
198
+ return span;
199
+ }, buildAnchorDecorationSpec({
200
+ diffId,
201
+ anchorType: AnchorTypeKey.to,
202
+ side: -1
203
+ }));
204
+ return [fromWidget, toWidget, ...maybeLeftAnchor];
205
+ };