@atlaskit/editor-plugin-show-diff 6.2.5 → 6.2.6

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 (43) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +1 -2
  3. package/dist/cjs/pm-plugins/decorations/colorSchemes/standard.js +19 -1
  4. package/dist/cjs/pm-plugins/decorations/colorSchemes/traditional.js +18 -2
  5. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +13 -10
  6. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +83 -14
  7. package/dist/cjs/pm-plugins/getScrollableDecorations.js +132 -0
  8. package/dist/cjs/pm-plugins/main.js +12 -25
  9. package/dist/cjs/pm-plugins/scrollToActiveDecoration.js +50 -9
  10. package/dist/cjs/showDiffPlugin.js +2 -1
  11. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +1 -2
  12. package/dist/es2019/pm-plugins/decorations/colorSchemes/standard.js +18 -0
  13. package/dist/es2019/pm-plugins/decorations/colorSchemes/traditional.js +17 -1
  14. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +13 -9
  15. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +80 -18
  16. package/dist/es2019/pm-plugins/getScrollableDecorations.js +117 -0
  17. package/dist/es2019/pm-plugins/main.js +11 -22
  18. package/dist/es2019/pm-plugins/scrollToActiveDecoration.js +50 -10
  19. package/dist/es2019/showDiffPlugin.js +3 -2
  20. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +1 -2
  21. package/dist/esm/pm-plugins/decorations/colorSchemes/standard.js +18 -0
  22. package/dist/esm/pm-plugins/decorations/colorSchemes/traditional.js +17 -1
  23. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +13 -10
  24. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +85 -16
  25. package/dist/esm/pm-plugins/getScrollableDecorations.js +124 -0
  26. package/dist/esm/pm-plugins/main.js +11 -24
  27. package/dist/esm/pm-plugins/scrollToActiveDecoration.js +50 -9
  28. package/dist/esm/showDiffPlugin.js +3 -2
  29. package/dist/types/pm-plugins/decorations/colorSchemes/standard.d.ts +4 -0
  30. package/dist/types/pm-plugins/decorations/colorSchemes/traditional.d.ts +3 -0
  31. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +5 -2
  32. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -1
  33. package/dist/types/pm-plugins/getScrollableDecorations.d.ts +27 -0
  34. package/dist/types/pm-plugins/main.d.ts +0 -2
  35. package/dist/types/pm-plugins/scrollToActiveDecoration.d.ts +4 -2
  36. package/dist/types-ts4.5/pm-plugins/decorations/colorSchemes/standard.d.ts +4 -0
  37. package/dist/types-ts4.5/pm-plugins/decorations/colorSchemes/traditional.d.ts +3 -0
  38. package/dist/types-ts4.5/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +5 -2
  39. package/dist/types-ts4.5/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -1
  40. package/dist/types-ts4.5/pm-plugins/getScrollableDecorations.d.ts +27 -0
  41. package/dist/types-ts4.5/pm-plugins/main.d.ts +0 -2
  42. package/dist/types-ts4.5/pm-plugins/scrollToActiveDecoration.d.ts +4 -2
  43. package/package.json +2 -2
@@ -0,0 +1,117 @@
1
+ /**
2
+ * True if `fragment` contains at least one inline node (text, hardBreak, emoji, mention, etc.).
3
+ * Block-only subtrees (e.g. empty paragraphs, block cards with no inline children) return false.
4
+ */
5
+ function fragmentContainsInlineContent(fragment) {
6
+ for (let i = 0; i < fragment.childCount; i++) {
7
+ const node = fragment.child(i);
8
+ if (node.isInline) {
9
+ return true;
10
+ }
11
+ if (node.content.size > 0 && fragmentContainsInlineContent(node.content)) {
12
+ return true;
13
+ }
14
+ }
15
+ return false;
16
+ }
17
+
18
+ /**
19
+ * Returns true when an inline decoration's [from, to) range can actually show in the document:
20
+ * positions are valid, and the slice contains at least one inline node ProseMirror would paint
21
+ * (not only empty block wrappers or block-only structure).
22
+ */
23
+ export function isInlineDiffDecorationRenderableInDoc(doc, from, to) {
24
+ try {
25
+ const slice = doc.slice(from, to);
26
+ return fragmentContainsInlineContent(slice.content);
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Checks if range1 is fully contained within range2
34
+ */
35
+ function isRangeFullyInside(range1Start, range1End, range2Start, range2End) {
36
+ return range2Start <= range1Start && range1End <= range2End;
37
+ }
38
+
39
+ /**
40
+ * Gets scrollable decorations from a DecorationSet, filtering out overlapping decorations
41
+ * and applying various rules for diff visualization.
42
+ *
43
+ * Rules:
44
+ * 1. Only includes diff-inline, diff-widget-* and diff-block decorations
45
+ * 2. Excludes listItem diff-block decorations (never scrollable)
46
+ * 3. Deduplicates diff-block decorations with same from, to and nodeName
47
+ * 4. When `doc` is passed: excludes diff-inline decorations whose range has no inline content
48
+ * (invalid positions, or block-only slices with no text/atoms — e.g. empty blocks)
49
+ * 5. Excludes diff-inline decorations that are fully contained within a diff-block
50
+ * 6. Excludes diff-block decorations that are fully contained within a diff-inline
51
+ * 7. Results are sorted by from position, then by to position
52
+ *
53
+ * @param set - The DecorationSet to extract scrollable decorations from
54
+ * @param doc - Current document; when set, diff-inline ranges are validated against this doc
55
+ * @returns Array of scrollable decorations, sorted and deduplicated
56
+ */
57
+ export const getScrollableDecorations = (set, doc) => {
58
+ if (!set) {
59
+ return [];
60
+ }
61
+ const seenBlockKeys = new Set();
62
+ const allDecorations = set.find(undefined, undefined, spec => {
63
+ var _spec$key;
64
+ return spec.key === 'diff-inline' || ((_spec$key = spec.key) === null || _spec$key === void 0 ? void 0 : _spec$key.startsWith('diff-widget')) || spec.key === 'diff-block';
65
+ });
66
+
67
+ // First pass: filter out listItem blocks and deduplicates blocks
68
+ const filtered = allDecorations.filter(dec => {
69
+ var _dec$spec, _dec$spec$nodeName, _dec$spec3;
70
+ if (((_dec$spec = dec.spec) === null || _dec$spec === void 0 ? void 0 : _dec$spec.key) === 'diff-block') {
71
+ var _dec$spec2;
72
+ // Skip listItem blocks as they are not scrollable
73
+ if (((_dec$spec2 = dec.spec) === null || _dec$spec2 === void 0 ? void 0 : _dec$spec2.nodeName) === 'listItem') return false;
74
+ }
75
+ const key = `${dec.from}-${dec.to}-${(_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 : ''}`;
76
+ // Skip blocks that have already been seen
77
+ if (seenBlockKeys.has(key)) return false;
78
+ seenBlockKeys.add(key);
79
+ return true;
80
+ });
81
+
82
+ // Separate decorations by type for easier processing
83
+ const blocks = filtered.filter(d => {
84
+ var _d$spec;
85
+ return ((_d$spec = d.spec) === null || _d$spec === void 0 ? void 0 : _d$spec.key) === 'diff-block';
86
+ });
87
+ const rawInlines = filtered.filter(d => {
88
+ var _d$spec2;
89
+ return ((_d$spec2 = d.spec) === null || _d$spec2 === void 0 ? void 0 : _d$spec2.key) === 'diff-inline';
90
+ });
91
+ const inlines = doc !== undefined ? rawInlines.filter(d => isInlineDiffDecorationRenderableInDoc(doc, d.from, d.to)) : rawInlines;
92
+ const widgets = filtered.filter(d => {
93
+ var _d$spec3, _d$spec3$key;
94
+ return (_d$spec3 = d.spec) === null || _d$spec3 === void 0 ? void 0 : (_d$spec3$key = _d$spec3.key) === null || _d$spec3$key === void 0 ? void 0 : _d$spec3$key.startsWith('diff-widget');
95
+ });
96
+
97
+ // Second pass: exclude overlapping decorations
98
+ // Rules:
99
+ // - If an inline is fully inside a block, exclude the block (inline takes priority)
100
+ // - If a block is fully inside an inline, exclude the block (inline takes priority)
101
+ const nonOverlappingBlocks = blocks.filter(block => {
102
+ // Exclude block if:
103
+ // 1. It's fully contained within any inline, OR
104
+ // 2. It fully contains any inline
105
+ return !inlines.some(inline => isRangeFullyInside(block.from, block.to, inline.from, inline.to) ||
106
+ // block inside inline
107
+ isRangeFullyInside(inline.from, inline.to, block.from, block.to) // inline inside block
108
+ );
109
+ });
110
+
111
+ // Combine all non-overlapping decorations
112
+ const result = [...nonOverlappingBlocks, ...inlines, ...widgets];
113
+
114
+ // Sort by from position, then by to position
115
+ result.sort((a, b) => a.from === b.from ? a.to - b.to : a.from - b.from);
116
+ return result;
117
+ };
@@ -7,29 +7,10 @@ import { fg } from '@atlaskit/platform-feature-flags';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
8
  import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
9
9
  import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
10
+ import { getScrollableDecorations } from './getScrollableDecorations';
10
11
  import { NodeViewSerializer } from './NodeViewSerializer';
11
12
  import { scrollToActiveDecoration } from './scrollToActiveDecoration';
12
13
  export const showDiffPluginKey = new PluginKey('showDiffPlugin');
13
- export const getScrollableDecorations = set => {
14
- var _set$find;
15
- const seenBlockKeys = new Set();
16
- return ((_set$find = set === null || set === void 0 ? void 0 : set.find(undefined, undefined, spec => {
17
- var _spec$key;
18
- return spec.key === 'diff-inline' || ((_spec$key = spec.key) === null || _spec$key === void 0 ? void 0 : _spec$key.startsWith('diff-widget')) || spec.key === 'diff-block';
19
- })) !== null && _set$find !== void 0 ? _set$find : []).filter(dec => {
20
- var _dec$spec;
21
- if (((_dec$spec = dec.spec) === null || _dec$spec === void 0 ? void 0 : _dec$spec.key) === 'diff-block') {
22
- var _dec$spec2, _dec$spec$nodeName, _dec$spec3;
23
- // Skip listItem blocks as they are not scrollable
24
- if (((_dec$spec2 = dec.spec) === null || _dec$spec2 === void 0 ? void 0 : _dec$spec2.nodeName) === 'listItem') return false;
25
- const key = `${dec.from}-${dec.to}-${(_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 : ''}`;
26
- // Skip blocks that have already been seen
27
- if (seenBlockKeys.has(key)) return false;
28
- seenBlockKeys.add(key);
29
- }
30
- return true;
31
- }).sort((a, b) => a.from === b.from ? a.to - b.to : a.from - b.from);
32
- };
33
14
  export const createPlugin = (config, getIntl, api) => {
34
15
  if (fg('platform_editor_show_diff_equality_fallback')) {
35
16
  enforceCustomStepRegisters();
@@ -103,7 +84,7 @@ export const createPlugin = (config, getIntl, api) => {
103
84
  };
104
85
  } else if (((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') && fg('platform_editor_show_diff_scroll_navigation')) {
105
86
  // Update the active index in plugin state and recalculate decorations
106
- const decorations = getScrollableDecorations(currentPluginState.decorations);
87
+ const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc);
107
88
  if (decorations.length > 0) {
108
89
  var _currentPluginState$a;
109
90
  // Initialize to -1 if undefined so that the first "next" scroll takes us to index 0 (first change).
@@ -161,6 +142,7 @@ export const createPlugin = (config, getIntl, api) => {
161
142
  setNodeViewSerializer(editorView);
162
143
  let isFirst = true;
163
144
  let previousActiveIndex;
145
+ let cancelPendingScrollToDecoration = null;
164
146
  return {
165
147
  update(view) {
166
148
  // If we're using configuration to show diffs we initialise here once we setup the editor view
@@ -179,9 +161,16 @@ export const createPlugin = (config, getIntl, api) => {
179
161
  const activeIndexChanged = (pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && pluginState.activeIndex !== previousActiveIndex;
180
162
  previousActiveIndex = pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex;
181
163
  if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && activeIndexChanged) {
182
- scrollToActiveDecoration(view, getScrollableDecorations(pluginState.decorations), pluginState.activeIndex);
164
+ var _cancelPendingScrollT;
165
+ (_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 ? void 0 : _cancelPendingScrollT();
166
+ cancelPendingScrollToDecoration = scrollToActiveDecoration(view, getScrollableDecorations(pluginState.decorations, view.state.doc), pluginState.activeIndex);
183
167
  }
184
168
  }
169
+ },
170
+ destroy() {
171
+ var _cancelPendingScrollT2;
172
+ (_cancelPendingScrollT2 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT2 === void 0 ? void 0 : _cancelPendingScrollT2();
173
+ cancelPendingScrollToDecoration = null;
185
174
  }
186
175
  };
187
176
  },
@@ -1,26 +1,66 @@
1
+ /**
2
+ * Extra space above the scrolled-to element so it does not sit flush under the
3
+ * viewport edge (helps with sticky table headers, toolbars, etc.).
4
+ *
5
+ * Implemented with `scroll-margin-top` so we still use the browser’s native
6
+ * `scrollIntoView`, which scrolls every relevant scrollport (nested containers
7
+ * and the window). A single manual `scrollTop` on one ancestor often misses
8
+ * outer scroll or mis-identifies the active scroll container.
9
+ */
10
+ const SCROLL_TOP_MARGIN_PX = 100;
11
+
1
12
  /**
2
13
  * Scrolls to the current position/selection of the document. It does the same as scrollIntoView()
3
14
  * but without requiring the focus on the editor, thus it can be called at any time.
4
15
  */
5
- function scrollToSelection(view, position) {
6
- const {
7
- node
8
- } = view.domAtPos(position);
9
- if (node instanceof Element) {
10
- node.scrollIntoView({
16
+ function scrollToSelection(node) {
17
+ const element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
18
+ if (!(element instanceof HTMLElement)) {
19
+ return;
20
+ }
21
+
22
+ // scroll-margin is included in scroll-into-view math; it does not change layout.
23
+ const previousScrollMarginTop = element.style.scrollMarginTop;
24
+ element.style.scrollMarginTop = `${SCROLL_TOP_MARGIN_PX}px`;
25
+ try {
26
+ element.scrollIntoView({
11
27
  behavior: 'smooth',
12
- block: 'center'
28
+ block: 'start'
13
29
  });
30
+ } finally {
31
+ element.style.scrollMarginTop = previousScrollMarginTop;
14
32
  }
15
33
  }
16
34
 
17
35
  /**
18
- * Scrolls the editor view to the decoration at the given index.
36
+ * Schedules scrolling to the decoration at the given index after the next frame.
37
+ *
38
+ * @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
19
39
  */
20
40
  export const scrollToActiveDecoration = (view, decorations, activeIndex) => {
21
41
  const decoration = decorations[activeIndex];
22
42
  if (!decoration) {
23
- return;
43
+ return () => {};
24
44
  }
25
- scrollToSelection(view, decoration === null || decoration === void 0 ? void 0 : decoration.from);
45
+ let rafId = requestAnimationFrame(() => {
46
+ var _decoration$spec;
47
+ rafId = null;
48
+ if (((_decoration$spec = decoration.spec) === null || _decoration$spec === void 0 ? void 0 : _decoration$spec.key) === 'diff-widget-active') {
49
+ var _decoration$type;
50
+ // @ts-expect-error - decoration.type is not typed public API
51
+ const widgetDom = decoration === null || decoration === void 0 ? void 0 : (_decoration$type = decoration.type) === null || _decoration$type === void 0 ? void 0 : _decoration$type.toDOM;
52
+ scrollToSelection(widgetDom);
53
+ } else {
54
+ var _view$domAtPos;
55
+ const targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
56
+ const node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
57
+ scrollToSelection(node);
58
+ }
59
+ });
60
+ return () => {
61
+ if (rafId !== null) {
62
+ cancelAnimationFrame(rafId);
63
+ rafId = null;
64
+ }
65
+ };
26
66
  };
@@ -1,5 +1,6 @@
1
1
  import { fg } from '@atlaskit/platform-feature-flags';
2
- import { createPlugin, showDiffPluginKey, getScrollableDecorations } from './pm-plugins/main';
2
+ import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
3
+ import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
3
4
  export const showDiffPlugin = ({
4
5
  api,
5
6
  config
@@ -54,7 +55,7 @@ export const showDiffPlugin = ({
54
55
  };
55
56
  }
56
57
  const pluginState = showDiffPluginKey.getState(editorState);
57
- const decorationCount = fg('platform_editor_show_diff_scroll_navigation') ? getScrollableDecorations(pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations) : (pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
58
+ const decorationCount = fg('platform_editor_show_diff_scroll_navigation') ? getScrollableDecorations(pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations, editorState.doc) : (pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
58
59
  return {
59
60
  isDisplayingChanges: decorationCount.length > 0,
60
61
  activeIndex: pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex,
@@ -167,7 +167,6 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
167
167
  }))));
168
168
  }
169
169
  if (change.deleted.length > 0) {
170
- var _isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.fromB === activeIndexPos.to;
171
170
  var decoration = createNodeChangedDecorationWidget(_objectSpread({
172
171
  change: change,
173
172
  doc: originalDoc,
@@ -175,7 +174,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
175
174
  colorScheme: colorScheme,
176
175
  newDoc: tr.doc,
177
176
  intl: intl,
178
- isActive: _isActive
177
+ activeIndexPos: activeIndexPos
179
178
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) && {
180
179
  isInserted: !isInserted
181
180
  }));
@@ -59,14 +59,32 @@ export var deletedStyleQuoteNodeWithLozenge = convertToInlineCss({
59
59
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-gray, #7D818A)"),
60
60
  borderRadius: "var(--ds-radius-small, 4px)"
61
61
  });
62
+
63
+ /** Stronger outline when this deleted block decoration is the active scroll target */
64
+ export var deletedStyleQuoteNodeWithLozengeActive = convertToInlineCss({
65
+ marginTop: "var(--ds-space-150, 12px)",
66
+ paddingTop: "var(--ds-space-025, 2px)",
67
+ paddingBottom: "var(--ds-space-025, 2px)",
68
+ paddingLeft: "var(--ds-space-025, 2px)",
69
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-accent-red, #E2483D)"),
70
+ borderRadius: "var(--ds-radius-small, 4px)"
71
+ });
62
72
  export var deletedBlockOutline = convertToInlineCss({
63
73
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-gray, #7D818A)"),
64
74
  borderRadius: "var(--ds-radius-small, 4px)"
65
75
  });
76
+ export var deletedBlockOutlineActive = convertToInlineCss({
77
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-accent-red, #E2483D)"),
78
+ borderRadius: "var(--ds-radius-small, 4px)"
79
+ });
66
80
  export var deletedBlockOutlineRounded = convertToInlineCss({
67
81
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-gray, #7D818A)"),
68
82
  borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
69
83
  });
84
+ export var deletedBlockOutlineRoundedActive = convertToInlineCss({
85
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-accent-red, #E2483D)"),
86
+ borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
87
+ });
70
88
  export var deletedRowStyle = convertToInlineCss({
71
89
  color: "var(--ds-text-accent-gray, #505258)",
72
90
  textDecoration: 'line-through',
@@ -44,7 +44,7 @@ export var deletedTraditionalContentStyleUnboundedActive = convertToInlineCss({
44
44
  top: '50%',
45
45
  width: '100%',
46
46
  display: 'inline-block',
47
- borderTop: "1px solid ".concat("var(--ds-text-accent-red-bolder, #5D1F1A)"),
47
+ borderTop: "2px solid ".concat("var(--ds-border-accent-red, #E2483D)"),
48
48
  pointerEvents: 'none',
49
49
  zIndex: 1
50
50
  });
@@ -56,14 +56,30 @@ export var deletedTraditionalStyleQuoteNode = convertToInlineCss({
56
56
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-red, #E2483D)"),
57
57
  borderRadius: "var(--ds-radius-small, 4px)"
58
58
  });
59
+ export var deletedTraditionalStyleQuoteNodeActive = convertToInlineCss({
60
+ marginTop: "var(--ds-space-150, 12px)",
61
+ paddingTop: "var(--ds-space-025, 2px)",
62
+ paddingBottom: "var(--ds-space-025, 2px)",
63
+ paddingLeft: "var(--ds-space-025, 2px)",
64
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-accent-red, #E2483D)"),
65
+ borderRadius: "var(--ds-radius-small, 4px)"
66
+ });
59
67
  export var deletedTraditionalBlockOutline = convertToInlineCss({
60
68
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-red, #E2483D)"),
61
69
  borderRadius: "var(--ds-radius-small, 4px)"
62
70
  });
71
+ export var deletedTraditionalBlockOutlineActive = convertToInlineCss({
72
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-accent-red, #E2483D)"),
73
+ borderRadius: "var(--ds-radius-small, 4px)"
74
+ });
63
75
  export var deletedTraditionalBlockOutlineRounded = convertToInlineCss({
64
76
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-red, #E2483D)"),
65
77
  borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
66
78
  });
79
+ export var deletedTraditionalBlockOutlineRoundedActive = convertToInlineCss({
80
+ boxShadow: "0 0 0 2px ".concat("var(--ds-border-accent-red, #E2483D)"),
81
+ borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
82
+ });
67
83
  export var deletedTraditionalRowStyle = convertToInlineCss({
68
84
  textDecorationColor: "var(--ds-border-accent-red, #E2483D)",
69
85
  textDecoration: 'line-through',
@@ -1,6 +1,7 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
3
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
4
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
6
  import { editingStyle, editingStyleActive, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleNewActive, deletedContentStyleUnbounded } from './colorSchemes/standard';
6
7
  import { traditionalInsertStyle, traditionalInsertStyleActive, deletedTraditionalContentStyle, deletedTraditionalContentStyleActive, deletedTraditionalContentStyleUnbounded, deletedTraditionalContentStyleUnboundedActive } from './colorSchemes/traditional';
@@ -79,13 +80,13 @@ var createContentWrapper = function createContentWrapper(colorScheme) {
79
80
  } else {
80
81
  wrapper.setAttribute('style', "".concat(baseStyle).concat(getDeletedContentStyle(colorScheme, isActive)));
81
82
  var strikethrough = document.createElement('span');
82
- strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme));
83
+ strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme, isActive));
83
84
  wrapper.append(strikethrough);
84
85
  }
85
86
  } else {
86
87
  wrapper.setAttribute('style', "".concat(baseStyle).concat(getDeletedContentStyle(colorScheme, isActive)));
87
88
  var _strikethrough = document.createElement('span');
88
- _strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme));
89
+ _strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme, isActive));
89
90
  wrapper.append(_strikethrough);
90
91
  }
91
92
  return wrapper;
@@ -96,18 +97,23 @@ var createContentWrapper = function createContentWrapper(colorScheme) {
96
97
  * that is not in the current document.
97
98
  */
98
99
  export var createNodeChangedDecorationWidget = function createNodeChangedDecorationWidget(_ref2) {
100
+ var _slice$content, _slice$content2, _slice$content3;
99
101
  var change = _ref2.change,
100
102
  doc = _ref2.doc,
101
103
  nodeViewSerializer = _ref2.nodeViewSerializer,
102
104
  colorScheme = _ref2.colorScheme,
103
105
  newDoc = _ref2.newDoc,
104
106
  intl = _ref2.intl,
105
- _ref2$isActive = _ref2.isActive,
106
- isActive = _ref2$isActive === void 0 ? false : _ref2$isActive,
107
+ activeIndexPos = _ref2.activeIndexPos,
107
108
  _ref2$isInserted = _ref2.isInserted,
108
109
  isInserted = _ref2$isInserted === void 0 ? false : _ref2$isInserted;
109
110
  var slice = doc.slice(change.fromA, change.toA);
110
- if (slice.content.content.length === 0) {
111
+ 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 && fg('platform_editor_show_diff_scroll_navigation');
112
+ // Widget decoration used for deletions as the content is not in the document
113
+ // and we want to display the deleted content with a style.
114
+ var safeInsertPos = findSafeInsertPos(newDoc, change.fromB, slice);
115
+ var isActive = activeIndexPos && safeInsertPos === activeIndexPos.from && safeInsertPos === activeIndexPos.to;
116
+ if (slice.content.content.length === 0 || shouldSkipDeletedEmptyParagraphDecoration) {
111
117
  return;
112
118
  }
113
119
  var isTableCellContent = slice.content.content.some(function () {
@@ -215,6 +221,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
215
221
  targetNode: node,
216
222
  colorScheme: colorScheme,
217
223
  intl: intl,
224
+ isActive: isActive,
218
225
  isInserted: isInserted
219
226
  });
220
227
  }
@@ -224,7 +231,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
224
231
  } else {
225
232
  var fallbackNode = fallbackSerialization();
226
233
  if (fallbackNode) {
227
- if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
234
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) || fg('platform_editor_show_diff_scroll_navigation')) {
228
235
  if (fallbackNode instanceof HTMLElement) {
229
236
  var injectedNode = injectInnerWrapper({
230
237
  node: fallbackNode,
@@ -247,10 +254,6 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
247
254
  }
248
255
  });
249
256
  dom.setAttribute('data-testid', 'show-diff-deleted-decoration');
250
-
251
- // Widget decoration used for deletions as the content is not in the document
252
- // and we want to display the deleted content with a style.
253
- var safeInsertPos = findSafeInsertPos(newDoc, change.fromB, slice);
254
257
  var decorations = [];
255
258
  decorations.push(Decoration.widget(safeInsertPos, dom, {
256
259
  key: "diff-widget-".concat(isActive ? 'active' : 'inactive')