@atlaskit/editor-plugin-show-diff 10.5.0 → 10.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +30 -3
- package/dist/cjs/pm-plugins/decorations/colorSchemes/standard.js +14 -1
- package/dist/cjs/pm-plugins/decorations/colorSchemes/traditional.js +15 -2
- package/dist/cjs/pm-plugins/decorations/createAnchorDecorationWidgets.js +52 -18
- package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +6 -1
- package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +23 -4
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +64 -4
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +30 -3
- package/dist/es2019/pm-plugins/decorations/colorSchemes/standard.js +13 -0
- package/dist/es2019/pm-plugins/decorations/colorSchemes/traditional.js +14 -1
- package/dist/es2019/pm-plugins/decorations/createAnchorDecorationWidgets.js +60 -28
- package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +8 -3
- package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +16 -1
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +53 -4
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +30 -3
- package/dist/esm/pm-plugins/decorations/colorSchemes/standard.js +13 -0
- package/dist/esm/pm-plugins/decorations/colorSchemes/traditional.js +14 -1
- package/dist/esm/pm-plugins/decorations/createAnchorDecorationWidgets.js +51 -18
- package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +8 -3
- package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +23 -4
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +63 -4
- package/dist/types/pm-plugins/decorations/colorSchemes/standard.d.ts +1 -0
- package/dist/types/pm-plugins/decorations/colorSchemes/traditional.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +4 -1
- package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +11 -1
- package/package.json +7 -7
|
@@ -136,6 +136,7 @@ export const createLeftAnchorWidget = ({
|
|
|
136
136
|
diffId,
|
|
137
137
|
anchorType: AnchorTypeKey.left
|
|
138
138
|
});
|
|
139
|
+
let leftResizeObserver;
|
|
139
140
|
return Decoration.widget(beforePos, (view, getPos) => {
|
|
140
141
|
// Outer span stays in the flow but takes up no space.
|
|
141
142
|
const wrapper = document.createElement('div');
|
|
@@ -150,13 +151,7 @@ export const createLeftAnchorWidget = ({
|
|
|
150
151
|
anchor.style.setProperty('left', `calc(50% - ${(edgeCase === null || edgeCase === void 0 ? void 0 : edgeCase.leftOffset) || 0}px)`);
|
|
151
152
|
anchor.style.setProperty('transform', 'translateX(-50%)');
|
|
152
153
|
wrapper.appendChild(anchor);
|
|
153
|
-
|
|
154
|
-
// The block DOM may not be settled synchronously (e.g. after a
|
|
155
|
-
// transaction), so defer the measurement like the gap cursor does.
|
|
156
|
-
requestAnimationFrame(() => {
|
|
157
|
-
// The widget may have been unmounted; bail if its position is gone.
|
|
158
|
-
// We still measure the stable block node position, not the widget's
|
|
159
|
-
// own position.
|
|
154
|
+
const measureWidth = () => {
|
|
160
155
|
if (getPos() === undefined || edgeCase.measurePos === undefined) {
|
|
161
156
|
return;
|
|
162
157
|
}
|
|
@@ -165,14 +160,35 @@ export const createLeftAnchorWidget = ({
|
|
|
165
160
|
// The left anchor only needs the container width so the
|
|
166
161
|
// IndicatorBar can align against the block's horizontal extent.
|
|
167
162
|
anchor.style.setProperty('width', `${dom.offsetWidth}px`);
|
|
163
|
+
|
|
164
|
+
// Observe the measured element for size changes (e.g. page
|
|
165
|
+
// resize) so the indicator stays aligned. CCI-17981
|
|
166
|
+
if (!leftResizeObserver) {
|
|
167
|
+
leftResizeObserver = new ResizeObserver(() => {
|
|
168
|
+
if (getPos() !== undefined) {
|
|
169
|
+
anchor.style.setProperty('width', `${dom.offsetWidth}px`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
leftResizeObserver.observe(dom);
|
|
173
|
+
}
|
|
168
174
|
}
|
|
169
|
-
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// The block DOM may not be settled synchronously (e.g. after a
|
|
178
|
+
// transaction), so defer the measurement like the gap cursor does.
|
|
179
|
+
requestAnimationFrame(measureWidth);
|
|
170
180
|
return wrapper;
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
}, {
|
|
182
|
+
...buildAnchorDecorationSpec({
|
|
183
|
+
diffId,
|
|
184
|
+
anchorType: AnchorTypeKey.left,
|
|
185
|
+
side: -999
|
|
186
|
+
}),
|
|
187
|
+
destroy: () => {
|
|
188
|
+
var _leftResizeObserver;
|
|
189
|
+
return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.disconnect();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
176
192
|
};
|
|
177
193
|
|
|
178
194
|
/**
|
|
@@ -229,6 +245,7 @@ export const createBlockIndicatorAnchorWidgets = ({
|
|
|
229
245
|
// Measure the actual cell/row DOM when inside one; otherwise measure the
|
|
230
246
|
// widget's own position.
|
|
231
247
|
const measurePos = parentCellOrRow ? parentCellOrRow.pos : from;
|
|
248
|
+
let blockResizeObserver;
|
|
232
249
|
const blockWidget = Decoration.widget(widgetPos, (view, getPos) => {
|
|
233
250
|
// Outer span stays in the flow but takes up no space.
|
|
234
251
|
const wrapper = document.createElement('span');
|
|
@@ -240,13 +257,7 @@ export const createBlockIndicatorAnchorWidgets = ({
|
|
|
240
257
|
anchor.style.setProperty('position', 'absolute');
|
|
241
258
|
anchor.style.setProperty('anchor-name', `--${blockAnchorKey}`);
|
|
242
259
|
wrapper.appendChild(anchor);
|
|
243
|
-
|
|
244
|
-
// The block DOM may not be settled synchronously (e.g. after a
|
|
245
|
-
// transaction), so defer the measurement like the gap cursor does.
|
|
246
|
-
requestAnimationFrame(() => {
|
|
247
|
-
// The widget may have been unmounted; bail if its position is gone.
|
|
248
|
-
// We still measure the stable cell/row node position, not the
|
|
249
|
-
// widget's own position.
|
|
260
|
+
const measureBlock = () => {
|
|
250
261
|
if (getPos() === undefined) {
|
|
251
262
|
return;
|
|
252
263
|
}
|
|
@@ -265,16 +276,37 @@ export const createBlockIndicatorAnchorWidgets = ({
|
|
|
265
276
|
// The offset already accounts for the cell/row's position, so the
|
|
266
277
|
// margin-top must not be double-applied.
|
|
267
278
|
anchor.style.setProperty('margin-top', '0px');
|
|
279
|
+
|
|
280
|
+
// Observe the measured element for size changes (e.g. page
|
|
281
|
+
// resize) so the indicator stays aligned. CCI-17981
|
|
282
|
+
if (!blockResizeObserver) {
|
|
283
|
+
blockResizeObserver = new ResizeObserver(() => {
|
|
284
|
+
if (getPos() !== undefined) {
|
|
285
|
+
measureBlock();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
blockResizeObserver.observe(dom);
|
|
289
|
+
}
|
|
268
290
|
}
|
|
269
|
-
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// The block DOM may not be settled synchronously (e.g. after a
|
|
294
|
+
// transaction), so defer the measurement like the gap cursor does.
|
|
295
|
+
requestAnimationFrame(measureBlock);
|
|
270
296
|
return wrapper;
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
297
|
+
}, {
|
|
298
|
+
...buildAnchorDecorationSpec({
|
|
299
|
+
diffId,
|
|
300
|
+
// Reuse the `from` anchor type slot; the generated key intentionally
|
|
301
|
+
// omits the anchor type so the single element backs top/bottom/left.
|
|
302
|
+
anchorType: AnchorTypeKey.from,
|
|
303
|
+
side: -1
|
|
304
|
+
}),
|
|
305
|
+
destroy: () => {
|
|
306
|
+
var _blockResizeObserver;
|
|
307
|
+
return (_blockResizeObserver = blockResizeObserver) === null || _blockResizeObserver === void 0 ? void 0 : _blockResizeObserver.disconnect();
|
|
308
|
+
}
|
|
309
|
+
});
|
|
278
310
|
return [blockWidget, ...maybeLeftAnchor];
|
|
279
311
|
};
|
|
280
312
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
2
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
3
4
|
import { isExtendedEnabled } from '../isExtendedEnabled';
|
|
4
|
-
import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle } from './colorSchemes/standard';
|
|
5
|
-
import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle } from './colorSchemes/traditional';
|
|
5
|
+
import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle, deletedCellOverlayRoundedStyle } from './colorSchemes/standard';
|
|
6
|
+
import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle, deletedTraditionalCellOverlayRoundedStyle } from './colorSchemes/traditional';
|
|
6
7
|
import { createBlockIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
|
|
7
8
|
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
8
9
|
const displayNoneStyle = convertToInlineCss({
|
|
@@ -143,7 +144,11 @@ export const createBlockChangedDecoration = ({
|
|
|
143
144
|
let style;
|
|
144
145
|
if (isExtendedEnabled(diffType) && ['tableCell', 'tableHeader'].includes(change.name)) {
|
|
145
146
|
const cellOverlay = document.createElement('div');
|
|
146
|
-
const
|
|
147
|
+
const isTraditional = colorScheme === 'traditional';
|
|
148
|
+
const isRoundedTable = expValEquals('platform_editor_table_diff_rounded_corners', 'isEnabled', true);
|
|
149
|
+
const addedCellStyle = isTraditional ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle;
|
|
150
|
+
const deletedCellStyle = isTraditional ? isRoundedTable ? deletedTraditionalCellOverlayRoundedStyle : deletedTraditionalCellOverlayStyle : isRoundedTable ? deletedCellOverlayRoundedStyle : deletedCellOverlayStyle;
|
|
151
|
+
const cellOverlayStyle = isInserted ? addedCellStyle : deletedCellStyle;
|
|
147
152
|
cellOverlay.setAttribute('style', cellOverlayStyle);
|
|
148
153
|
decorations.push(
|
|
149
154
|
// change.to - 1 to position the overlay inside the end of the cell
|
|
@@ -8,6 +8,16 @@ import { buildDiffDecorationSpec } from './decorationKeys';
|
|
|
8
8
|
const displayNoneStyle = convertToInlineCss({
|
|
9
9
|
display: 'none'
|
|
10
10
|
});
|
|
11
|
+
const getAtomicInlineNodeClassName = (inlineNodeName, colorScheme) => {
|
|
12
|
+
const classNames = ['show-diff-atomic-inline-changed'];
|
|
13
|
+
if (inlineNodeName) {
|
|
14
|
+
classNames.push(`show-diff-atomic-inline-changed-${inlineNodeName}`);
|
|
15
|
+
}
|
|
16
|
+
if (colorScheme === 'traditional') {
|
|
17
|
+
classNames.push('show-diff-atomic-inline-changed-traditional');
|
|
18
|
+
}
|
|
19
|
+
return classNames.join(' ');
|
|
20
|
+
};
|
|
11
21
|
/**
|
|
12
22
|
* Inline decoration used for insertions as the content already exists in the document
|
|
13
23
|
*
|
|
@@ -20,11 +30,13 @@ export const createInlineChangedDecoration = ({
|
|
|
20
30
|
colorScheme,
|
|
21
31
|
isActive = false,
|
|
22
32
|
isInserted = true,
|
|
33
|
+
isAtomicInlineNode = false,
|
|
23
34
|
shouldHideDeleted = false,
|
|
24
35
|
showIndicators = false,
|
|
25
36
|
doc,
|
|
26
37
|
diffType,
|
|
27
|
-
hideAddedDiffsUnderline = false
|
|
38
|
+
hideAddedDiffsUnderline = false,
|
|
39
|
+
inlineNodeName
|
|
28
40
|
}) => {
|
|
29
41
|
const diffId = crypto.randomUUID();
|
|
30
42
|
if (shouldHideDeleted) {
|
|
@@ -66,6 +78,9 @@ export const createInlineChangedDecoration = ({
|
|
|
66
78
|
}
|
|
67
79
|
const decorations = [Decoration.inline(change.fromB, change.toB, {
|
|
68
80
|
style,
|
|
81
|
+
...(isAtomicInlineNode && isInserted && {
|
|
82
|
+
class: getAtomicInlineNodeClassName(inlineNodeName, colorScheme)
|
|
83
|
+
}),
|
|
69
84
|
'data-testid': 'show-diff-changed-decoration'
|
|
70
85
|
}, buildDiffDecorationSpec({
|
|
71
86
|
decorationType: 'inline',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
2
2
|
import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
|
|
3
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
3
4
|
const filterUndefined = x => !!x;
|
|
4
5
|
|
|
5
6
|
// Attributes that indicate a change in media image
|
|
@@ -11,6 +12,24 @@ const dateAttrs = ['timestamp'];
|
|
|
11
12
|
// Attribute that indicates a task item state change
|
|
12
13
|
const taskItemAttrs = ['state'];
|
|
13
14
|
|
|
15
|
+
// Attributes that indicate an emoji change
|
|
16
|
+
const emojiAttrs = ['shortName', 'id', 'text'];
|
|
17
|
+
|
|
18
|
+
// Attributes that indicate a mention change (who is mentioned)
|
|
19
|
+
const mentionAttrs = ['id', 'text'];
|
|
20
|
+
|
|
21
|
+
// Attributes that indicate a status change (label or colour)
|
|
22
|
+
const statusAttrs = ['text', 'color'];
|
|
23
|
+
|
|
24
|
+
// Map of node type name → the attrs that represent a meaningful content change for that node
|
|
25
|
+
const inlineNodeAttrMap = {
|
|
26
|
+
date: dateAttrs,
|
|
27
|
+
emoji: emojiAttrs,
|
|
28
|
+
mention: mentionAttrs,
|
|
29
|
+
status: statusAttrs
|
|
30
|
+
};
|
|
31
|
+
const isInlineAttrChangeNodeName = nodeName => nodeName in inlineNodeAttrMap;
|
|
32
|
+
|
|
14
33
|
// Attributes excluded from extension change detection (not meaningful content changes)
|
|
15
34
|
const extensionExcludedAttrs = ['localId'];
|
|
16
35
|
|
|
@@ -25,7 +44,7 @@ const getStepAttrs = step => {
|
|
|
25
44
|
}
|
|
26
45
|
return [];
|
|
27
46
|
};
|
|
28
|
-
export const getAttrChangeRanges = (doc, steps) => {
|
|
47
|
+
export const getAttrChangeRanges = (doc, steps, originalDoc) => {
|
|
29
48
|
return steps.map(step => {
|
|
30
49
|
if (!(step instanceof AttrStep) && !(step instanceof SetAttrsStep)) {
|
|
31
50
|
return undefined;
|
|
@@ -35,14 +54,38 @@ export const getAttrChangeRanges = (doc, steps) => {
|
|
|
35
54
|
const nodeAtPos = doc.nodeAt(step.pos);
|
|
36
55
|
|
|
37
56
|
// date node: timestamp attribute change — highlight the date node itself (inline)
|
|
38
|
-
if (stepAttrs.some(v => dateAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date') {
|
|
57
|
+
if (stepAttrs.some(v => dateAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
|
|
39
58
|
return {
|
|
40
59
|
fromB: step.pos,
|
|
41
60
|
toB: step.pos + nodeAtPos.nodeSize,
|
|
42
|
-
isInline: true
|
|
61
|
+
isInline: true,
|
|
62
|
+
inlineNodeName: 'date'
|
|
43
63
|
};
|
|
44
64
|
}
|
|
45
65
|
|
|
66
|
+
// The following inline node attr changes are gated behind platform_editor_improve_inline_diffs.
|
|
67
|
+
// The changeset path (createDecorationsForChange) handles the deletion widget via
|
|
68
|
+
// prosemirror-changeset; we only need to add the inline insertion highlight here.
|
|
69
|
+
if (expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true) && nodeAtPos) {
|
|
70
|
+
const nodeName = nodeAtPos.type.name;
|
|
71
|
+
if (isInlineAttrChangeNodeName(nodeName)) {
|
|
72
|
+
const watchedAttrs = inlineNodeAttrMap[nodeName];
|
|
73
|
+
if (stepAttrs.some(v => watchedAttrs.includes(v))) {
|
|
74
|
+
const originalNodeAtPos = originalDoc === null || originalDoc === void 0 ? void 0 : originalDoc.nodeAt(step.pos);
|
|
75
|
+
return {
|
|
76
|
+
fromB: step.pos,
|
|
77
|
+
toB: step.pos + nodeAtPos.nodeSize,
|
|
78
|
+
isInline: true,
|
|
79
|
+
inlineNodeName: nodeName,
|
|
80
|
+
...(originalNodeAtPos && {
|
|
81
|
+
fromA: step.pos,
|
|
82
|
+
toA: step.pos + originalNodeAtPos.nodeSize
|
|
83
|
+
})
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
46
89
|
// taskItem node: state attribute change — highlight the taskItem node
|
|
47
90
|
if (stepAttrs.some(v => taskItemAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'taskItem') {
|
|
48
91
|
return {
|
|
@@ -70,7 +113,13 @@ export const getAttrChangeRanges = (doc, steps) => {
|
|
|
70
113
|
};
|
|
71
114
|
}
|
|
72
115
|
return undefined;
|
|
73
|
-
}).filter(filterUndefined)
|
|
116
|
+
}).filter(filterUndefined)
|
|
117
|
+
// Deduplicate by node position: multiple AttrSteps on the same node
|
|
118
|
+
// (e.g. setNodeAttribute(pos, 'text', ...) + setNodeAttribute(pos, 'color', ...))
|
|
119
|
+
// should produce only one decoration, not one per step.
|
|
120
|
+
// Gated behind the same experiment as the inline node attr changes that introduced
|
|
121
|
+
// the possibility of multiple ranges for the same node position.
|
|
122
|
+
.filter((range, i, arr) => !expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true) || arr.findIndex(r => r.fromB === range.fromB) === i);
|
|
74
123
|
};
|
|
75
124
|
|
|
76
125
|
/**
|
|
@@ -421,16 +421,43 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
|
|
|
421
421
|
isInserted: true
|
|
422
422
|
})));
|
|
423
423
|
});
|
|
424
|
-
getAttrChangeRanges(tr.doc, attrSteps).forEach(function (change) {
|
|
424
|
+
getAttrChangeRanges(tr.doc, attrSteps, originalDoc).forEach(function (change) {
|
|
425
425
|
if (change.isInline) {
|
|
426
|
-
// Inline nodes (e.g. date) need an inline decoration rather than a block decoration
|
|
426
|
+
// Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
|
|
427
427
|
var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
|
|
428
|
+
var isAtomicInlineNodeFlag = expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
|
|
428
429
|
decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration({
|
|
429
430
|
change: change,
|
|
430
431
|
colorScheme: colorScheme,
|
|
431
432
|
isActive: isActive,
|
|
432
|
-
isInserted: true
|
|
433
|
+
isInserted: true,
|
|
434
|
+
isAtomicInlineNode: isAtomicInlineNodeFlag,
|
|
435
|
+
inlineNodeName: change.inlineNodeName,
|
|
436
|
+
// Suppress the border-bottom underline for atomic inline nodeviews —
|
|
437
|
+
// it doesn't render on custom nodeview DOM elements and is unnecessary noise.
|
|
438
|
+
hideAddedDiffsUnderline: isAtomicInlineNodeFlag,
|
|
439
|
+
diffType: diffType
|
|
433
440
|
})));
|
|
441
|
+
// If we have the original node position, also render the old node as a "deleted" widget
|
|
442
|
+
// so the user can see what it looked like before the change.
|
|
443
|
+
if (change.fromA !== undefined && change.toA !== undefined && expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
|
|
444
|
+
decorations.push.apply(decorations, _toConsumableArray(createNodeChangedDecorationWidget({
|
|
445
|
+
change: {
|
|
446
|
+
fromA: change.fromA,
|
|
447
|
+
toA: change.toA,
|
|
448
|
+
fromB: change.fromB,
|
|
449
|
+
toB: change.toB,
|
|
450
|
+
deleted: []
|
|
451
|
+
},
|
|
452
|
+
doc: originalDoc,
|
|
453
|
+
nodeViewSerializer: nodeViewSerializer,
|
|
454
|
+
colorScheme: colorScheme,
|
|
455
|
+
newDoc: tr.doc,
|
|
456
|
+
intl: intl,
|
|
457
|
+
activeIndexPos: activeIndexPos,
|
|
458
|
+
isInserted: false
|
|
459
|
+
})));
|
|
460
|
+
}
|
|
434
461
|
} else {
|
|
435
462
|
decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration({
|
|
436
463
|
doc: tr.doc,
|
|
@@ -180,4 +180,17 @@ export var deletedCellOverlayStyle = convertToInlineCss({
|
|
|
180
180
|
zIndex: 1,
|
|
181
181
|
outline: "1px solid ".concat("var(--ds-border-accent-gray, #7D818A)"),
|
|
182
182
|
pointerEvents: 'none'
|
|
183
|
+
});
|
|
184
|
+
export var deletedCellOverlayRoundedStyle = convertToInlineCss({
|
|
185
|
+
position: 'absolute',
|
|
186
|
+
top: 0,
|
|
187
|
+
left: 0,
|
|
188
|
+
width: '100%',
|
|
189
|
+
height: '100%',
|
|
190
|
+
backgroundColor: "rgba(from ".concat("var(--ds-background-accent-gray-subtlest, #F0F1F2)", " r g b / 0.5)"),
|
|
191
|
+
zIndex: 2,
|
|
192
|
+
outline: "1px solid ".concat("var(--ds-border-accent-gray, #7D818A)"),
|
|
193
|
+
pointerEvents: 'none',
|
|
194
|
+
border: 'inherit',
|
|
195
|
+
borderRadius: 'inherit'
|
|
183
196
|
});
|
|
@@ -84,7 +84,7 @@ export var deletedTraditionalBlockOutlineRoundedActive = convertToInlineCss({
|
|
|
84
84
|
borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
/** Scroll-navigation “new” emphasis: 4px ring
|
|
87
|
+
/** Scroll-navigation “new” emphasis: 4px ring. */
|
|
88
88
|
export var deletedTraditionalBlockOutlineNew = convertToInlineCss({
|
|
89
89
|
boxShadow: "0 0 0 4px ".concat("var(--ds-background-accent-red-subtlest, #FFECEB)"),
|
|
90
90
|
borderRadius: "var(--ds-radius-small, 4px)"
|
|
@@ -205,4 +205,17 @@ export var deletedTraditionalCellOverlayStyle = convertToInlineCss({
|
|
|
205
205
|
zIndex: 1,
|
|
206
206
|
outline: "1px solid ".concat("var(--ds-border-disabled, #0515240F)"),
|
|
207
207
|
pointerEvents: 'none'
|
|
208
|
+
});
|
|
209
|
+
export var deletedTraditionalCellOverlayRoundedStyle = convertToInlineCss({
|
|
210
|
+
position: 'absolute',
|
|
211
|
+
top: 0,
|
|
212
|
+
left: 0,
|
|
213
|
+
width: '100%',
|
|
214
|
+
height: '100%',
|
|
215
|
+
backgroundColor: "rgba(from ".concat("var(--ds-background-accent-gray-subtlest, #F0F1F2)", " r g b / 0.5)"),
|
|
216
|
+
zIndex: 2,
|
|
217
|
+
outline: "1px solid ".concat("var(--ds-border-disabled, #0515240F)"),
|
|
218
|
+
pointerEvents: 'none',
|
|
219
|
+
border: 'inherit',
|
|
220
|
+
borderRadius: 'inherit'
|
|
208
221
|
});
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
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
|
+
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; }
|
|
1
4
|
import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
2
5
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
3
6
|
import { buildAnchorDecorationKey, buildAnchorDecorationSpec, AnchorDocMarginKey, AnchorTypeKey } from './decorationKeys';
|
|
@@ -133,6 +136,7 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
|
|
|
133
136
|
diffId: diffId,
|
|
134
137
|
anchorType: AnchorTypeKey.left
|
|
135
138
|
});
|
|
139
|
+
var leftResizeObserver;
|
|
136
140
|
return Decoration.widget(beforePos, function (view, getPos) {
|
|
137
141
|
// Outer span stays in the flow but takes up no space.
|
|
138
142
|
var wrapper = document.createElement('div');
|
|
@@ -147,13 +151,7 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
|
|
|
147
151
|
anchor.style.setProperty('left', "calc(50% - ".concat((edgeCase === null || edgeCase === void 0 ? void 0 : edgeCase.leftOffset) || 0, "px)"));
|
|
148
152
|
anchor.style.setProperty('transform', 'translateX(-50%)');
|
|
149
153
|
wrapper.appendChild(anchor);
|
|
150
|
-
|
|
151
|
-
// The block DOM may not be settled synchronously (e.g. after a
|
|
152
|
-
// transaction), so defer the measurement like the gap cursor does.
|
|
153
|
-
requestAnimationFrame(function () {
|
|
154
|
-
// The widget may have been unmounted; bail if its position is gone.
|
|
155
|
-
// We still measure the stable block node position, not the widget's
|
|
156
|
-
// own position.
|
|
154
|
+
var measureWidth = function measureWidth() {
|
|
157
155
|
if (getPos() === undefined || edgeCase.measurePos === undefined) {
|
|
158
156
|
return;
|
|
159
157
|
}
|
|
@@ -162,13 +160,33 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
|
|
|
162
160
|
// The left anchor only needs the container width so the
|
|
163
161
|
// IndicatorBar can align against the block's horizontal extent.
|
|
164
162
|
anchor.style.setProperty('width', "".concat(dom.offsetWidth, "px"));
|
|
163
|
+
|
|
164
|
+
// Observe the measured element for size changes (e.g. page
|
|
165
|
+
// resize) so the indicator stays aligned. CCI-17981
|
|
166
|
+
if (!leftResizeObserver) {
|
|
167
|
+
leftResizeObserver = new ResizeObserver(function () {
|
|
168
|
+
if (getPos() !== undefined) {
|
|
169
|
+
anchor.style.setProperty('width', "".concat(dom.offsetWidth, "px"));
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
leftResizeObserver.observe(dom);
|
|
173
|
+
}
|
|
165
174
|
}
|
|
166
|
-
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// The block DOM may not be settled synchronously (e.g. after a
|
|
178
|
+
// transaction), so defer the measurement like the gap cursor does.
|
|
179
|
+
requestAnimationFrame(measureWidth);
|
|
167
180
|
return wrapper;
|
|
168
|
-
}, buildAnchorDecorationSpec({
|
|
181
|
+
}, _objectSpread(_objectSpread({}, buildAnchorDecorationSpec({
|
|
169
182
|
diffId: diffId,
|
|
170
183
|
anchorType: AnchorTypeKey.left,
|
|
171
184
|
side: -999
|
|
185
|
+
})), {}, {
|
|
186
|
+
destroy: function destroy() {
|
|
187
|
+
var _leftResizeObserver;
|
|
188
|
+
return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.disconnect();
|
|
189
|
+
}
|
|
172
190
|
}));
|
|
173
191
|
};
|
|
174
192
|
|
|
@@ -229,6 +247,7 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
|
|
|
229
247
|
// Measure the actual cell/row DOM when inside one; otherwise measure the
|
|
230
248
|
// widget's own position.
|
|
231
249
|
var measurePos = parentCellOrRow ? parentCellOrRow.pos : from;
|
|
250
|
+
var blockResizeObserver;
|
|
232
251
|
var blockWidget = Decoration.widget(widgetPos, function (view, getPos) {
|
|
233
252
|
// Outer span stays in the flow but takes up no space.
|
|
234
253
|
var wrapper = document.createElement('span');
|
|
@@ -240,13 +259,7 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
|
|
|
240
259
|
anchor.style.setProperty('position', 'absolute');
|
|
241
260
|
anchor.style.setProperty('anchor-name', "--".concat(blockAnchorKey));
|
|
242
261
|
wrapper.appendChild(anchor);
|
|
243
|
-
|
|
244
|
-
// The block DOM may not be settled synchronously (e.g. after a
|
|
245
|
-
// transaction), so defer the measurement like the gap cursor does.
|
|
246
|
-
requestAnimationFrame(function () {
|
|
247
|
-
// The widget may have been unmounted; bail if its position is gone.
|
|
248
|
-
// We still measure the stable cell/row node position, not the
|
|
249
|
-
// widget's own position.
|
|
262
|
+
var _measureBlock = function measureBlock() {
|
|
250
263
|
if (getPos() === undefined) {
|
|
251
264
|
return;
|
|
252
265
|
}
|
|
@@ -265,15 +278,35 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
|
|
|
265
278
|
// The offset already accounts for the cell/row's position, so the
|
|
266
279
|
// margin-top must not be double-applied.
|
|
267
280
|
anchor.style.setProperty('margin-top', '0px');
|
|
281
|
+
|
|
282
|
+
// Observe the measured element for size changes (e.g. page
|
|
283
|
+
// resize) so the indicator stays aligned. CCI-17981
|
|
284
|
+
if (!blockResizeObserver) {
|
|
285
|
+
blockResizeObserver = new ResizeObserver(function () {
|
|
286
|
+
if (getPos() !== undefined) {
|
|
287
|
+
_measureBlock();
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
blockResizeObserver.observe(dom);
|
|
291
|
+
}
|
|
268
292
|
}
|
|
269
|
-
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// The block DOM may not be settled synchronously (e.g. after a
|
|
296
|
+
// transaction), so defer the measurement like the gap cursor does.
|
|
297
|
+
requestAnimationFrame(_measureBlock);
|
|
270
298
|
return wrapper;
|
|
271
|
-
}, buildAnchorDecorationSpec({
|
|
299
|
+
}, _objectSpread(_objectSpread({}, buildAnchorDecorationSpec({
|
|
272
300
|
diffId: diffId,
|
|
273
301
|
// Reuse the `from` anchor type slot; the generated key intentionally
|
|
274
302
|
// omits the anchor type so the single element backs top/bottom/left.
|
|
275
303
|
anchorType: AnchorTypeKey.from,
|
|
276
304
|
side: -1
|
|
305
|
+
})), {}, {
|
|
306
|
+
destroy: function destroy() {
|
|
307
|
+
var _blockResizeObserver;
|
|
308
|
+
return (_blockResizeObserver = blockResizeObserver) === null || _blockResizeObserver === void 0 ? void 0 : _blockResizeObserver.disconnect();
|
|
309
|
+
}
|
|
277
310
|
}));
|
|
278
311
|
return [blockWidget].concat(maybeLeftAnchor);
|
|
279
312
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
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 { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
5
|
import { isExtendedEnabled } from '../isExtendedEnabled';
|
|
5
|
-
import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle } from './colorSchemes/standard';
|
|
6
|
-
import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle } from './colorSchemes/traditional';
|
|
6
|
+
import { standardDecorationMarkerVariable, deletedDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle, deletedCellOverlayRoundedStyle } from './colorSchemes/standard';
|
|
7
|
+
import { traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle, deletedTraditionalCellOverlayRoundedStyle } from './colorSchemes/traditional';
|
|
7
8
|
import { createBlockIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
|
|
8
9
|
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
9
10
|
var displayNoneStyle = convertToInlineCss({
|
|
@@ -148,7 +149,11 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
|
|
|
148
149
|
var style;
|
|
149
150
|
if (isExtendedEnabled(diffType) && ['tableCell', 'tableHeader'].includes(change.name)) {
|
|
150
151
|
var cellOverlay = document.createElement('div');
|
|
151
|
-
var
|
|
152
|
+
var isTraditional = colorScheme === 'traditional';
|
|
153
|
+
var isRoundedTable = expValEquals('platform_editor_table_diff_rounded_corners', 'isEnabled', true);
|
|
154
|
+
var addedCellStyle = isTraditional ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle;
|
|
155
|
+
var deletedCellStyle = isTraditional ? isRoundedTable ? deletedTraditionalCellOverlayRoundedStyle : deletedTraditionalCellOverlayStyle : isRoundedTable ? deletedCellOverlayRoundedStyle : deletedCellOverlayStyle;
|
|
156
|
+
var cellOverlayStyle = isInserted ? addedCellStyle : deletedCellStyle;
|
|
152
157
|
cellOverlay.setAttribute('style', cellOverlayStyle);
|
|
153
158
|
decorations.push(
|
|
154
159
|
// change.to - 1 to position the overlay inside the end of the cell
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
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; }
|
|
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; }
|
|
2
5
|
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
3
6
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
4
7
|
import { isExtendedEnabled } from '../isExtendedEnabled';
|
|
@@ -9,6 +12,16 @@ import { buildDiffDecorationSpec } from './decorationKeys';
|
|
|
9
12
|
var displayNoneStyle = convertToInlineCss({
|
|
10
13
|
display: 'none'
|
|
11
14
|
});
|
|
15
|
+
var getAtomicInlineNodeClassName = function getAtomicInlineNodeClassName(inlineNodeName, colorScheme) {
|
|
16
|
+
var classNames = ['show-diff-atomic-inline-changed'];
|
|
17
|
+
if (inlineNodeName) {
|
|
18
|
+
classNames.push("show-diff-atomic-inline-changed-".concat(inlineNodeName));
|
|
19
|
+
}
|
|
20
|
+
if (colorScheme === 'traditional') {
|
|
21
|
+
classNames.push('show-diff-atomic-inline-changed-traditional');
|
|
22
|
+
}
|
|
23
|
+
return classNames.join(' ');
|
|
24
|
+
};
|
|
12
25
|
/**
|
|
13
26
|
* Inline decoration used for insertions as the content already exists in the document
|
|
14
27
|
*
|
|
@@ -23,6 +36,8 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
|
|
|
23
36
|
isActive = _ref$isActive === void 0 ? false : _ref$isActive,
|
|
24
37
|
_ref$isInserted = _ref.isInserted,
|
|
25
38
|
isInserted = _ref$isInserted === void 0 ? true : _ref$isInserted,
|
|
39
|
+
_ref$isAtomicInlineNo = _ref.isAtomicInlineNode,
|
|
40
|
+
isAtomicInlineNode = _ref$isAtomicInlineNo === void 0 ? false : _ref$isAtomicInlineNo,
|
|
26
41
|
_ref$shouldHideDelete = _ref.shouldHideDeleted,
|
|
27
42
|
shouldHideDeleted = _ref$shouldHideDelete === void 0 ? false : _ref$shouldHideDelete,
|
|
28
43
|
_ref$showIndicators = _ref.showIndicators,
|
|
@@ -30,7 +45,8 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
|
|
|
30
45
|
doc = _ref.doc,
|
|
31
46
|
diffType = _ref.diffType,
|
|
32
47
|
_ref$hideAddedDiffsUn = _ref.hideAddedDiffsUnderline,
|
|
33
|
-
hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn
|
|
48
|
+
hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn,
|
|
49
|
+
inlineNodeName = _ref.inlineNodeName;
|
|
34
50
|
var diffId = crypto.randomUUID();
|
|
35
51
|
if (shouldHideDeleted) {
|
|
36
52
|
return [Decoration.inline(change.fromB, change.toB, {
|
|
@@ -69,10 +85,13 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
|
|
|
69
85
|
style = isActive ? editingStyleActive : editingStyle;
|
|
70
86
|
}
|
|
71
87
|
}
|
|
72
|
-
var decorations = [Decoration.inline(change.fromB, change.toB, {
|
|
73
|
-
style: style
|
|
88
|
+
var decorations = [Decoration.inline(change.fromB, change.toB, _objectSpread(_objectSpread({
|
|
89
|
+
style: style
|
|
90
|
+
}, isAtomicInlineNode && isInserted && {
|
|
91
|
+
class: getAtomicInlineNodeClassName(inlineNodeName, colorScheme)
|
|
92
|
+
}), {}, {
|
|
74
93
|
'data-testid': 'show-diff-changed-decoration'
|
|
75
|
-
}, buildDiffDecorationSpec({
|
|
94
|
+
}), buildDiffDecorationSpec({
|
|
76
95
|
decorationType: 'inline',
|
|
77
96
|
diffId: diffId,
|
|
78
97
|
isActive: isActive
|