@atlaskit/editor-plugin-show-diff 29.0.1 → 30.0.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 (58) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +7 -30
  3. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +0 -39
  4. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +3 -16
  5. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +3 -6
  6. package/dist/cjs/pm-plugins/decorations/createReplacedCellDecorations.js +0 -2
  7. package/dist/cjs/pm-plugins/decorations/utils/createDeletedLineBreakWidget.js +4 -7
  8. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +5 -24
  9. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +2 -4
  10. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +1 -5
  11. package/dist/cjs/pm-plugins/main.js +7 -26
  12. package/dist/cjs/showDiffPlugin.js +0 -43
  13. package/dist/cjs/showDiffPluginType.js +0 -12
  14. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +7 -30
  15. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +0 -37
  16. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +1 -17
  17. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +3 -6
  18. package/dist/es2019/pm-plugins/decorations/createReplacedCellDecorations.js +0 -2
  19. package/dist/es2019/pm-plugins/decorations/utils/createDeletedLineBreakWidget.js +4 -7
  20. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +6 -24
  21. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +3 -6
  22. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +2 -8
  23. package/dist/es2019/pm-plugins/main.js +7 -27
  24. package/dist/es2019/showDiffPlugin.js +0 -38
  25. package/dist/es2019/showDiffPluginType.js +0 -12
  26. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +7 -30
  27. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +0 -37
  28. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +3 -16
  29. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +3 -6
  30. package/dist/esm/pm-plugins/decorations/createReplacedCellDecorations.js +0 -2
  31. package/dist/esm/pm-plugins/decorations/utils/createDeletedLineBreakWidget.js +4 -7
  32. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +5 -24
  33. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +2 -4
  34. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +1 -5
  35. package/dist/esm/pm-plugins/main.js +7 -26
  36. package/dist/esm/showDiffPlugin.js +0 -43
  37. package/dist/esm/showDiffPluginType.js +0 -12
  38. package/dist/types/entry-points/show-diff-plugin-type.d.ts +1 -1
  39. package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +1 -2
  40. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +0 -24
  41. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +1 -3
  42. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +1 -3
  43. package/dist/types/pm-plugins/decorations/createReplacedCellDecorations.d.ts +1 -3
  44. package/dist/types/pm-plugins/decorations/utils/createDeletedLineBreakWidget.d.ts +3 -6
  45. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -4
  46. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.d.ts +1 -1
  47. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.d.ts +1 -1
  48. package/dist/types/pm-plugins/main.d.ts +1 -6
  49. package/dist/types/showDiffPluginType.d.ts +0 -27
  50. package/package.json +7 -13
  51. package/dist/cjs/pm-plugins/decorations/revealStyles.js +0 -160
  52. package/dist/cjs/pm-plugins/revealAnimation.js +0 -524
  53. package/dist/es2019/pm-plugins/decorations/revealStyles.js +0 -143
  54. package/dist/es2019/pm-plugins/revealAnimation.js +0 -495
  55. package/dist/esm/pm-plugins/decorations/revealStyles.js +0 -153
  56. package/dist/esm/pm-plugins/revealAnimation.js +0 -518
  57. package/dist/types/pm-plugins/decorations/revealStyles.d.ts +0 -49
  58. package/dist/types/pm-plugins/revealAnimation.d.ts +0 -33
@@ -1,524 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.rebindReveal = exports.cancelReveal = exports.beginReveal = exports.REVEAL_DEFAULT_DURATION_MS = void 0;
8
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
- var _revealStyles = require("./decorations/revealStyles");
10
- /**
11
- * Reveal animation timing. Phase A (0–0.6D): outgoing state fades in, agent highlight wipes out.
12
- * Phase B (0.6D–D): all highlights wipe in. Uses Web Animations API for element reusability and
13
- * per-reveal cancellation.
14
- */
15
-
16
- /** Total choreography length when the caller does not specify one. */
17
- var REVEAL_DEFAULT_DURATION_MS = exports.REVEAL_DEFAULT_DURATION_MS = 950;
18
-
19
- /**
20
- * The reflow settles slightly ahead of the highlights. Running it for the full duration makes the
21
- * movement read as sluggish next to the cross-fade, which is finished well before it.
22
- */
23
- var REFLOW_DURATION_FRACTION = 0.8;
24
-
25
- /** Share of the total spent cross-fading before the highlights come back. */
26
- var PHASE_A_FRACTION = 0.6;
27
- var EASING = 'ease-in-out';
28
-
29
- /** Selector for agent highlights in the outgoing snapshot. */
30
- var CHANGED_DECORATION_SELECTOR = '[data-testid="show-diff-changed-decoration"]';
31
-
32
- /**
33
- * Every marker that identifies a block as changed, in either the outgoing or incoming render.
34
- * Deleted content is a widget in the incoming state only; reveal markers exist only while revealing.
35
- */
36
- var CHANGED_BLOCK_SELECTOR = ['[data-testid="show-diff-changed-decoration"]', '[data-testid="show-diff-deleted-decoration"]', "[".concat(_revealStyles.REVEAL_ATTR, "]")].join(', ');
37
-
38
- /** Elements that re-mount on clone; replace with placeholders to preserve layout. */
39
- var REMOUNT_UNSAFE_SELECTOR = 'iframe, object, embed, video, audio, canvas';
40
-
41
- /**
42
- * Marks animations this module owns, so a re-bind can tell them from anything else on the node.
43
- * Suffixed per purpose because one element can legitimately carry several — a changed block that
44
- * also grows takes both the cross-fade and the clip.
45
- */
46
- var REVEAL_ID = {
47
- clock: 'show-diff-reveal-clock',
48
- fade: 'show-diff-reveal-fade',
49
- reflow: 'show-diff-reveal-reflow',
50
- wipe: 'show-diff-reveal-wipe'
51
- };
52
- /** `property` distinguishes the clip from the carry, since one block can need both. */
53
-
54
- var running = new WeakMap();
55
-
56
- /**
57
- * Stop any running reveal and drop it from plugin state.
58
- *
59
- * Clearing the state is what restores the resting appearance: revealing decorations paint their
60
- * highlight at zero width, so the repaint that follows is what renders them normally again. Doing
61
- * it in state rather than by writing styles onto the current elements means decorations rendered
62
- * later are correct too — an imperative fix only reaches the elements that exist at that instant.
63
- */
64
- var cancelReveal = exports.cancelReveal = function cancelReveal(editorView) {
65
- var _current$overlay, _current$restoreReflo;
66
- var current = running.get(editorView);
67
- if (!current) {
68
- return;
69
- }
70
- running.delete(editorView);
71
- [].concat((0, _toConsumableArray2.default)(current.outgoing), (0, _toConsumableArray2.default)(current.incoming)).forEach(function (animation) {
72
- return animation.cancel();
73
- });
74
- (_current$overlay = current.overlay) === null || _current$overlay === void 0 || _current$overlay.remove();
75
- (_current$restoreReflo = current.restoreReflow) === null || _current$restoreReflo === void 0 || _current$restoreReflo.call(current);
76
- current.complete();
77
- };
78
-
79
- /**
80
- * Sanitise cloned subtree: remove IDs, contenteditable, re-mount-unsafe elements.
81
- * Measures embeds from LIVE element (clone is detached, would measure 0x0).
82
- */
83
- var sanitiseClone = function sanitiseClone(live, clone) {
84
- clone.removeAttribute('id');
85
- clone.querySelectorAll('[id]').forEach(function (element) {
86
- return element.removeAttribute('id');
87
- });
88
- clone.removeAttribute('contenteditable');
89
- clone.querySelectorAll('[contenteditable]').forEach(function (element) {
90
- element.removeAttribute('contenteditable');
91
- });
92
- // Revealing decorations paint at zero width; snapshot must show full width so clear markers here.
93
- clone.querySelectorAll("[".concat(_revealStyles.REVEAL_ATTR, "]")).forEach(function (element) {
94
- element.removeAttribute(_revealStyles.REVEAL_ATTR);
95
- element.style.removeProperty('background-size');
96
- });
97
- var liveEmbeds = live.querySelectorAll(REMOUNT_UNSAFE_SELECTOR);
98
- clone.querySelectorAll(REMOUNT_UNSAFE_SELECTOR).forEach(function (element, index) {
99
- var placeholder = document.createElement('div');
100
- var source = liveEmbeds[index];
101
- if (source) {
102
- var _source$getBoundingCl = source.getBoundingClientRect(),
103
- width = _source$getBoundingCl.width,
104
- height = _source$getBoundingCl.height;
105
- placeholder.style.width = "".concat(width, "px");
106
- placeholder.style.height = "".concat(height, "px");
107
- }
108
- element.replaceWith(placeholder);
109
- });
110
- };
111
-
112
- /**
113
- * Convert flat highlights (from non-revealing render) to wipeable gradients.
114
- * Reads colour from LIVE element (clone is detached, no computed style).
115
- */
116
- var makeOutgoingHighlightsWipeable = function makeOutgoingHighlightsWipeable(liveBlock, clonedBlock) {
117
- var live = liveBlock.querySelectorAll(CHANGED_DECORATION_SELECTOR);
118
- var cloned = clonedBlock.querySelectorAll(CHANGED_DECORATION_SELECTOR);
119
- var wipeable = [];
120
- cloned.forEach(function (clone, index) {
121
- var _clone$getAttribute;
122
- var source = live[index];
123
- if (!source) {
124
- return;
125
- }
126
- // Read colour from custom property (revealing render) or computed style (flat render).
127
- var color = source.style.getPropertyValue(_revealStyles.REVEAL_BG_VAR).trim() || window.getComputedStyle(source).backgroundColor;
128
- if (!color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)') {
129
- return;
130
- }
131
- clone.setAttribute('style', "".concat((_clone$getAttribute = clone.getAttribute('style')) !== null && _clone$getAttribute !== void 0 ? _clone$getAttribute : '').concat((0, _revealStyles.buildWipeableBackground)(color)));
132
- // Anchor right: shrinking retracts the highlight through the right edge.
133
- clone.style.backgroundSize = '100% 100%';
134
- clone.style.backgroundPosition = '100% 0';
135
- wipeable.push(clone);
136
- });
137
- return wipeable;
138
- };
139
-
140
- /**
141
- * The contiguous run of top-level blocks containing a change.
142
- *
143
- * Only these cross-fade. Fading the whole content area would also fade blocks that did not change
144
- * and have merely been pushed up or down by the reflow, which reads as the entire document
145
- * flickering.
146
- *
147
- * Exact rather than contiguous: an agent can touch two paragraphs either side of untouched ones,
148
- * and a first-to-last range would sweep up everything between them. The index travels with each
149
- * block so its outgoing height can be paired with its incoming height across the swap.
150
- */
151
- var findChangedBlocks = function findChangedBlocks(content) {
152
- return Array.from(content.children).filter(function (child) {
153
- return child instanceof HTMLElement;
154
- }).map(function (block, index) {
155
- return {
156
- block: block,
157
- index: index
158
- };
159
- }).filter(function (_ref) {
160
- var block = _ref.block;
161
- return block.matches(CHANGED_BLOCK_SELECTOR) || block.querySelector(CHANGED_BLOCK_SELECTOR);
162
- });
163
- };
164
-
165
- /** Outgoing height of every changed block, keyed by its position among the content's children. */
166
- var measureBlocks = function measureBlocks(changed) {
167
- return new Map(changed.map(function (_ref2) {
168
- var block = _ref2.block,
169
- index = _ref2.index;
170
- return [index, block.getBoundingClientRect().height];
171
- }));
172
- };
173
-
174
- /**
175
- * Build and position a snapshot of the outgoing state over the changed blocks.
176
- *
177
- * The wrapper is a shallow clone of the ProseMirror element so the snapshot keeps the class-based
178
- * typography the real content has; a plain div would render the text differently. Inserted as a
179
- * sibling rather than a child so ProseMirror does not reconcile it away.
180
- */
181
- var buildOverlay = function buildOverlay(content, changed) {
182
- var host = content.parentElement;
183
- if (!host || !content.offsetParent || changed.length === 0) {
184
- return undefined;
185
- }
186
- var wrapper = content.cloneNode(false);
187
- if (!(wrapper instanceof HTMLElement)) {
188
- return undefined;
189
- }
190
- var contentRect = content.getBoundingClientRect();
191
- changed.forEach(function (_ref3) {
192
- var block = _ref3.block;
193
- var clone = block.cloneNode(true);
194
- if (!(clone instanceof HTMLElement)) {
195
- return;
196
- }
197
- sanitiseClone(block, clone);
198
- makeOutgoingHighlightsWipeable(block, clone);
199
-
200
- // Each clone is placed at its own offset. Stacking them in flow would close the gaps left by
201
- // the unchanged blocks that were not copied, so a later block would sit too high.
202
- var rect = block.getBoundingClientRect();
203
- clone.style.position = 'absolute';
204
- clone.style.top = "".concat(rect.top - contentRect.top, "px");
205
- clone.style.left = "".concat(rect.left - contentRect.left, "px");
206
- clone.style.width = "".concat(rect.width, "px");
207
- clone.style.margin = '0';
208
- wrapper.appendChild(clone);
209
- });
210
- wrapper.removeAttribute('id');
211
- wrapper.removeAttribute('contenteditable');
212
- // aria-hidden + inert removes overlay from focus, hit-testing and AT (aria-hidden-focus safe).
213
- wrapper.setAttribute('aria-hidden', 'true');
214
- wrapper.setAttribute('inert', '');
215
- wrapper.style.position = 'absolute';
216
- // Sits on the content box, with the clones positioned relative to it.
217
- wrapper.style.top = "".concat(content.offsetTop, "px");
218
- wrapper.style.left = "".concat(content.offsetLeft, "px");
219
- wrapper.style.width = "".concat(content.offsetWidth, "px");
220
- // The wrapper inherits the editor's own padding and margin, which would offset the copied blocks
221
- // a second time on top of the position already measured from them.
222
- wrapper.style.margin = '0';
223
- wrapper.style.padding = '0';
224
- wrapper.style.boxSizing = 'border-box';
225
- wrapper.style.pointerEvents = 'none';
226
- wrapper.style.zIndex = '1';
227
- host.insertBefore(wrapper, content);
228
- return wrapper;
229
- };
230
-
231
- /**
232
- * Slide the content below the change from where it used to sit to where it now sits.
233
- *
234
- * The incoming blocks are already at their final height, so without this everything below them
235
- * jumps the instant the diff is applied. `margin-bottom` carries the following content; when the
236
- * change has grown, the last block is also clipped back to its old height and released, so the
237
- * content below is not overlapped while it catches up.
238
- */
239
- var animateReflow = function animateReflow(changed, outgoingHeights, duration) {
240
- var _changed$;
241
- var specs = [];
242
- var restores = [];
243
- var deltas = new Map();
244
- changed.forEach(function (_ref4) {
245
- var block = _ref4.block,
246
- index = _ref4.index;
247
- var before = outgoingHeights.get(index);
248
- if (before === undefined) {
249
- return;
250
- }
251
- var delta = before - block.getBoundingClientRect().height;
252
- if (Math.abs(delta) < 1) {
253
- return;
254
- }
255
- deltas.set(index, delta);
256
-
257
- // Growth only: clip the block back to its old height and open it up. Without this the taller
258
- // new content would overlap the content below, which has not caught up yet.
259
- var growth = Math.max(0, -delta);
260
- if (growth === 0) {
261
- return;
262
- }
263
- var previousOverflow = block.style.overflow;
264
- block.style.overflow = 'hidden';
265
- restores.push(function () {
266
- block.style.overflow = previousOverflow;
267
- });
268
- specs.push({
269
- index: index,
270
- keyframes: [{
271
- clipPath: "inset(0 0 ".concat(growth, "px 0)")
272
- }, {
273
- clipPath: 'inset(0 0 0 0)'
274
- }],
275
- property: 'clip'
276
- });
277
- });
278
- var parent = (_changed$ = changed[0]) === null || _changed$ === void 0 ? void 0 : _changed$.block.parentElement;
279
- if (deltas.size === 0 || !parent) {
280
- return {
281
- restore: function restore() {
282
- return restores.forEach(function (restore) {
283
- return restore();
284
- });
285
- },
286
- specs: specs
287
- };
288
- }
289
-
290
- // Everything below a change is carried with `transform`, never `margin`. Margin is a layout
291
- // property, so each frame would re-lay-out the content below at a fractional offset and
292
- // re-rasterise its text — that reads as shimmer even at a locked 60fps. Transforms run on the
293
- // compositor: the glyphs are rasterised once and moved.
294
- var carried = 0;
295
- Array.from(parent.children).forEach(function (child, index) {
296
- var _deltas$get;
297
- if (child instanceof HTMLElement && carried !== 0) {
298
- specs.push({
299
- index: index,
300
- keyframes: [{
301
- transform: "translateY(".concat(carried, "px)")
302
- }, {
303
- transform: 'translateY(0px)'
304
- }],
305
- property: 'carry'
306
- });
307
- }
308
- // Applied after the block itself: a change moves the content below it, not its own top edge.
309
- carried += (_deltas$get = deltas.get(index)) !== null && _deltas$get !== void 0 ? _deltas$get : 0;
310
- });
311
- return {
312
- restore: function restore() {
313
- return restores.forEach(function (restore) {
314
- return restore();
315
- });
316
- },
317
- specs: specs
318
- };
319
- };
320
-
321
- /** Animate incoming highlights; re-run if diff repaints mid-reveal. */
322
- /**
323
- * Creates an animation unless the element already carries one of ours, and resumes it at `elapsed`.
324
- *
325
- * ProseMirror rebuilds inline decorations on any repaint, which destroys animations bound to them.
326
- * Widget DOM is reused and so survives, which is why deleted highlights used to animate while added
327
- * ones snapped in. Re-binding at the elapsed time keeps a re-rendered element in step rather than
328
- * restarting it from the beginning.
329
- */
330
- var bind = function bind(entry, element, id, keyframes, options, elapsed) {
331
- if (element.getAnimations().some(function (animation) {
332
- return animation.id === id;
333
- })) {
334
- return;
335
- }
336
- var animation = element.animate(keyframes, options);
337
- animation.id = id;
338
- if (elapsed > 0) {
339
- animation.currentTime = Math.min(elapsed, options.duration);
340
- }
341
- entry.incoming.push(animation);
342
- };
343
- var highlightKeyframes = function highlightKeyframes(element) {
344
- var border = element.style.getPropertyValue(_revealStyles.REVEAL_BORDER_VAR).trim();
345
- return [{
346
- backgroundSize: '0% 100%',
347
- borderBottomColor: 'transparent',
348
- offset: 0
349
- }, {
350
- backgroundSize: '0% 100%',
351
- borderBottomColor: 'transparent',
352
- easing: EASING,
353
- offset: PHASE_A_FRACTION
354
- }, {
355
- backgroundSize: '100% 100%',
356
- borderBottomColor: border,
357
- offset: 1
358
- }];
359
- };
360
-
361
- /** (Re)binds every animation that runs on live, ProseMirror-managed DOM. */
362
- var applyIncoming = function applyIncoming(entry, content, total, phaseA) {
363
- var elapsed = Math.max(0, performance.now() - entry.startedAt);
364
- var changedBlocks = findChangedBlocks(content);
365
-
366
- // Only the changed blocks cross-fade. Everything else is unchanged content that has merely
367
- // moved, and fading it would read as the whole document flickering.
368
- if (entry.overlay) {
369
- var fading = changedBlocks.length > 0 ? changedBlocks.map(function (_ref5) {
370
- var block = _ref5.block;
371
- return block;
372
- }) : [content];
373
- fading.forEach(function (block) {
374
- bind(entry, block, REVEAL_ID.fade, [{
375
- opacity: 0
376
- }, {
377
- opacity: 1
378
- }], {
379
- duration: phaseA,
380
- easing: EASING,
381
- fill: 'forwards'
382
- }, elapsed);
383
- });
384
- }
385
- content.querySelectorAll("[".concat(_revealStyles.REVEAL_ATTR, "]")).forEach(function (element) {
386
- bind(entry, element, REVEAL_ID.wipe, highlightKeyframes(element), {
387
- duration: total,
388
- fill: 'forwards'
389
- }, elapsed);
390
- });
391
- entry.reflowSpecs.forEach(function (_ref6) {
392
- var index = _ref6.index,
393
- keyframes = _ref6.keyframes,
394
- property = _ref6.property;
395
- var child = content.children[index];
396
- if (child instanceof HTMLElement) {
397
- bind(entry, child, "".concat(REVEAL_ID.reflow, "-").concat(property), keyframes, {
398
- duration: entry.reflowDuration,
399
- easing: EASING,
400
- fill: 'backwards'
401
- }, elapsed);
402
- }
403
- });
404
- };
405
-
406
- /**
407
- * Re-binds the reveal to the current decorations. Called on every repaint while a reveal is in
408
- * flight, because a repaint silently destroys any animation attached to re-rendered DOM.
409
- */
410
- var rebindReveal = exports.rebindReveal = function rebindReveal(editorView, content) {
411
- var entry = running.get(editorView);
412
- if (entry) {
413
- applyIncoming(entry, content, entry.total, entry.phaseA);
414
- }
415
- };
416
- var scheduleIncoming = function scheduleIncoming(editorView, entry, content, total, phaseA) {
417
- requestAnimationFrame(function () {
418
- if (running.get(editorView) !== entry) {
419
- return;
420
- }
421
- entry.startedAt = performance.now();
422
- var reflow = animateReflow(findChangedBlocks(content), entry.outgoingHeights, entry.reflowDuration);
423
- entry.reflowSpecs = reflow.specs;
424
- entry.restoreReflow = reflow.restore;
425
- applyIncoming(entry, content, total, phaseA);
426
-
427
- // The clock runs on the content root, which ProseMirror never replaces. Hanging completion
428
- // off a decoration animation would strand the reveal whenever that decoration was rebuilt.
429
- var clock = content.animate([{
430
- opacity: 1
431
- }, {
432
- opacity: 1
433
- }], {
434
- duration: total
435
- });
436
- clock.id = REVEAL_ID.clock;
437
- clock.onfinish = function () {
438
- if (running.get(editorView) === entry) {
439
- cancelReveal(editorView);
440
- }
441
- };
442
- entry.incoming.push(clock);
443
- });
444
- };
445
-
446
- /**
447
- * Start the reveal. Must be called BEFORE transaction dispatch (last moment outgoing DOM exists
448
- * for capture). Incoming half animates a frame later, post-decoration-render.
449
- */
450
- var beginReveal = exports.beginReveal = function beginReveal(_ref7) {
451
- var _reveal$durationMs;
452
- var editorView = _ref7.editorView,
453
- onComplete = _ref7.onComplete,
454
- reveal = _ref7.reveal;
455
- if (typeof window === 'undefined' || typeof document === 'undefined') {
456
- return;
457
- }
458
- var content = editorView.dom;
459
- if (!(content instanceof HTMLElement)) {
460
- return;
461
- }
462
- var total = (_reveal$durationMs = reveal.durationMs) !== null && _reveal$durationMs !== void 0 ? _reveal$durationMs : REVEAL_DEFAULT_DURATION_MS;
463
- var phaseA = Math.round(total * PHASE_A_FRACTION);
464
-
465
- // Repaint mid-reveal: reuse snapshot (not retake), rebind incoming animations to fresh decorations.
466
- var existing = running.get(editorView);
467
- if (existing) {
468
- existing.incoming.forEach(function (animation) {
469
- return animation.cancel();
470
- });
471
- existing.incoming = [];
472
- scheduleIncoming(editorView, existing, content, total, phaseA);
473
- return;
474
- }
475
-
476
- // Captured before dispatch: this is the last moment the outgoing layout can be measured.
477
- var outgoingBlocks = findChangedBlocks(content);
478
- var overlay = buildOverlay(content, outgoingBlocks);
479
- var outgoing = [];
480
- if (overlay) {
481
- // fill: 'forwards' is load-bearing: default fill: 'none' snaps snapshot to opaque (reads as swap).
482
- var fadeOut = overlay.animate([{
483
- opacity: 1
484
- }, {
485
- opacity: 0
486
- }], {
487
- duration: phaseA,
488
- easing: EASING,
489
- fill: 'forwards'
490
- });
491
- fadeOut.onfinish = function () {
492
- overlay.remove();
493
- };
494
- outgoing.push(fadeOut);
495
- overlay.querySelectorAll(CHANGED_DECORATION_SELECTOR).forEach(function (element) {
496
- if (!element.style.backgroundImage) {
497
- return;
498
- }
499
- outgoing.push(element.animate([{
500
- backgroundSize: '100% 100%'
501
- }, {
502
- backgroundSize: '0% 100%'
503
- }], {
504
- duration: phaseA,
505
- easing: EASING,
506
- fill: 'forwards'
507
- }));
508
- });
509
- }
510
- var entry = {
511
- complete: onComplete,
512
- incoming: [],
513
- outgoing: outgoing,
514
- outgoingHeights: measureBlocks(outgoingBlocks),
515
- phaseA: phaseA,
516
- reflowDuration: Math.round(total * REFLOW_DURATION_FRACTION),
517
- reflowSpecs: [],
518
- startedAt: performance.now(),
519
- total: total,
520
- overlay: overlay
521
- };
522
- running.set(editorView, entry);
523
- scheduleIncoming(editorView, entry, content, total, phaseA);
524
- };
@@ -1,143 +0,0 @@
1
- import { agentBrandColorSchemes } from '@atlaskit/agent-color/agent-brand-color-schemes';
2
- import { convertToInlineCss } from '@atlaskit/editor-common/css-helper';
3
- import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
4
- import { buildDeletedInlineStyleStandard, getDeletedInlineRevealColors, getInsertedInlineRevealColors } from './colorSchemes/factory';
5
- import { colorSchemeRegistry } from './colorSchemes/schemes';
6
- import { getStandardDeletedContentStyle, getStandardDeletedContentStyleActive } from './colorSchemes/standard';
7
- /**
8
- * Painting strategy for reveal highlights. Highlights are `linear-gradient`s with animated
9
- * `background-size` for the wipe effect. Colours live on elements as custom properties so the
10
- * attribution palette works per-contributor.
11
- */
12
-
13
- /** Marks an element as taking part in the reveal, and says which side it represents. */
14
- export const REVEAL_ATTR = 'data-show-diff-reveal';
15
- /** Wipe colour, read by the animation as the gradient's colour stop. */
16
- export const REVEAL_BG_VAR = '--show-diff-reveal-bg';
17
-
18
- /** Underline colour, brought in on the same schedule as the highlight. */
19
- export const REVEAL_BORDER_VAR = '--show-diff-reveal-border';
20
-
21
- /** Only schemes with background highlights can be revealed; 'traditional' uses underline only. */
22
- const schemeSupportsReveal = colorScheme => colorScheme !== 'traditional';
23
-
24
- /** Convert a flat background colour into a wipeable gradient (zero width initially). */
25
- export const buildWipeableBackground = color => convertToInlineCss({
26
- backgroundColor: 'transparent',
27
- backgroundImage: `linear-gradient(${color}, ${color})`,
28
- backgroundRepeat: 'no-repeat',
29
- backgroundSize: '0% 100%',
30
- backgroundPosition: '0 0',
31
- // Each line fragment of a wrapped highlight gets its own background box, so they wipe
32
- // together rather than the gradient stretching across the whole wrapped run.
33
- WebkitBoxDecorationBreak: 'clone',
34
- boxDecorationBreak: 'clone'
35
- });
36
-
37
- /** Base padding and transparent underline placeholder (no layout shift on reveal). */
38
- const revealBaseStyle = convertToInlineCss({
39
- padding: `1px 0 2px`,
40
- borderBottom: `2px solid transparent`
41
- });
42
- const buildRevealVariables = ({
43
- background,
44
- border
45
- }) => convertToInlineCss({
46
- [REVEAL_BG_VAR]: background,
47
- [REVEAL_BORDER_VAR]: border
48
- });
49
-
50
- /** Configuration that affects both resting state and reveal endpoint. */
51
-
52
- /** Reveal colours from the refactored scheme registry (attribution palette ready). */
53
- const revealColorsRefactored = (colors, {
54
- hideAddedDiffsUnderline,
55
- isActive,
56
- isInserted
57
- }) => isInserted ? getInsertedInlineRevealColors(colors, isActive, hideAddedDiffsUnderline) : getDeletedInlineRevealColors(colors);
58
-
59
- /**
60
- * Legacy cohort reveal colours. Values MUST match `revealColorsRefactored()` output for
61
- * `standard` scheme (test: `revealStyles.ts` in test package).
62
- */
63
- const revealColorsLegacy = ({
64
- hideAddedDiffsUnderline,
65
- isActive,
66
- isInserted
67
- }) => isInserted ? {
68
- // Mirrors `editingStyleExtended` / `editingStyleActiveExtended` and their
69
- // `*NoUnderline` variants in `colorSchemes/standard.ts`.
70
- background: isActive ? "var(--ds-background-accent-purple-subtler-pressed, #D8A0F7)" : "var(--ds-background-accent-purple-subtlest, #F8EEFE)",
71
- border: hideAddedDiffsUnderline ? 'transparent' : "var(--ds-border-accent-purple, #AF59E1)"
72
- } : {
73
- // Mirrors `deletedInlineContentStyleExtended` in `colorSchemes/standard.ts`.
74
- background: "var(--ds-background-accent-gray-subtlest, #F0F1F2)",
75
- border: "var(--ds-border-accent-gray, #7D818A)"
76
- };
77
- const resolveRevealColors = (colors, variant) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? revealColorsRefactored(colors, variant) : revealColorsLegacy(variant);
78
- const getColorScheme = colorScheme => colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
79
-
80
- /** Deleted text appearance (grey and strikethrough) without the highlight. */
81
- const deletedTextOnlyStyle = (colors, isActive) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? buildDeletedInlineStyleStandard(colors, isActive ? 'active' : 'default') : isActive ? getStandardDeletedContentStyleActive() : getStandardDeletedContentStyle();
82
-
83
- /**
84
- * Resolve reveal attribute and style for a decoration. Returned style REPLACES the decoration's
85
- * highlight (not an addition) so the animation has something to wipe. Gate resolved in showDiff
86
- * command for single shared answer between decorations and animation.
87
- */
88
- export const resolveRevealStyle = ({
89
- colorScheme,
90
- hideAddedDiffsUnderline = false,
91
- includeDeletedTextStyle = true,
92
- isActive,
93
- isInserted,
94
- reveal
95
- }) => {
96
- if ((reveal === null || reveal === void 0 ? void 0 : reveal.mode) !== 'phased' || !schemeSupportsReveal(colorScheme)) {
97
- return undefined;
98
- }
99
- const colors = getColorScheme(colorScheme);
100
- const brand = isInserted && Object.prototype.hasOwnProperty.call(agentBrandColorSchemes, colors.insertColor) ? agentBrandColorSchemes[colors.insertColor] : undefined;
101
- const {
102
- background,
103
- border
104
- } = resolveRevealColors(colors, {
105
- hideAddedDiffsUnderline,
106
- isActive,
107
- isInserted
108
- });
109
- return {
110
- role: isInserted ? 'added' : 'deleted',
111
- style: (brand ? convertToInlineCss({
112
- color: brand.text
113
- }) : '') + (isInserted || !includeDeletedTextStyle ? '' : deletedTextOnlyStyle(colors, isActive)) + revealBaseStyle + buildWipeableBackground(background) + buildRevealVariables({
114
- background,
115
- border
116
- })
117
- };
118
- };
119
-
120
- /** Reveal style for imperatively-built elements (deleted-content widget wrappers). */
121
- export const applyRevealToElement = ({
122
- colorScheme,
123
- element,
124
- hideAddedDiffsUnderline,
125
- isActive,
126
- isInserted,
127
- reveal
128
- }) => {
129
- const resolved = resolveRevealStyle({
130
- colorScheme,
131
- hideAddedDiffsUnderline,
132
- isActive,
133
- isInserted,
134
- reveal,
135
- // The widget supplies the deleted text's own grey/strikethrough styling already.
136
- includeDeletedTextStyle: false
137
- });
138
- if (!resolved) {
139
- return '';
140
- }
141
- element.setAttribute(REVEAL_ATTR, resolved.role);
142
- return resolved.style;
143
- };