@atlaskit/editor-plugin-show-diff 14.5.1 → 15.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 (74) hide show
  1. package/CHANGELOG.md +34 -6
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +3 -9
  3. package/dist/cjs/pm-plugins/calculateDiff/smart/classifySmartChanges.js +1 -2
  4. package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +21 -4
  5. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +6 -56
  6. package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +6 -20
  7. package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +4 -6
  8. package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -2
  9. package/dist/cjs/pm-plugins/decorations/createContributorTagWidget.js +14 -29
  10. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +1 -2
  11. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +2 -25
  12. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +1 -2
  13. package/dist/cjs/pm-plugins/main.js +4 -4
  14. package/dist/cjs/showDiffPlugin.js +4 -5
  15. package/dist/cjs/ui/ContributorTag/buildContributorTagDom.js +122 -0
  16. package/dist/cjs/ui/ContributorTag/contributorAvatarRenderer.js +140 -0
  17. package/dist/cjs/ui/ContributorTag/contributorTagController.js +500 -0
  18. package/dist/cjs/ui/ContributorTag/contributorTagIcons.js +46 -0
  19. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +3 -5
  20. package/dist/es2019/pm-plugins/calculateDiff/smart/classifySmartChanges.js +1 -2
  21. package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +20 -3
  22. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +6 -55
  23. package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +14 -26
  24. package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +4 -6
  25. package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -2
  26. package/dist/es2019/pm-plugins/decorations/createContributorTagWidget.js +16 -30
  27. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +1 -2
  28. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +2 -17
  29. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +1 -2
  30. package/dist/es2019/pm-plugins/main.js +4 -4
  31. package/dist/es2019/showDiffPlugin.js +4 -5
  32. package/dist/es2019/ui/ContributorTag/buildContributorTagDom.js +110 -0
  33. package/dist/es2019/ui/ContributorTag/contributorAvatarRenderer.js +136 -0
  34. package/dist/es2019/ui/ContributorTag/contributorTagController.js +403 -0
  35. package/dist/es2019/ui/ContributorTag/contributorTagIcons.js +40 -0
  36. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +3 -9
  37. package/dist/esm/pm-plugins/calculateDiff/smart/classifySmartChanges.js +1 -2
  38. package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +21 -4
  39. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +6 -57
  40. package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +7 -20
  41. package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +4 -6
  42. package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -2
  43. package/dist/esm/pm-plugins/decorations/createContributorTagWidget.js +15 -30
  44. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +1 -2
  45. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +2 -25
  46. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +1 -2
  47. package/dist/esm/pm-plugins/main.js +4 -4
  48. package/dist/esm/showDiffPlugin.js +4 -5
  49. package/dist/esm/ui/ContributorTag/buildContributorTagDom.js +115 -0
  50. package/dist/esm/ui/ContributorTag/contributorAvatarRenderer.js +135 -0
  51. package/dist/esm/ui/ContributorTag/contributorTagController.js +493 -0
  52. package/dist/esm/ui/ContributorTag/contributorTagIcons.js +40 -0
  53. package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +3 -3
  54. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +2 -2
  55. package/dist/types/pm-plugins/decorations/colorSchemes/schemes.d.ts +1 -1
  56. package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +13 -16
  57. package/dist/types/pm-plugins/decorations/createContributorTagWidget.d.ts +11 -9
  58. package/dist/types/pm-plugins/main.d.ts +1 -2
  59. package/dist/types/ui/ContributorTag/buildContributorTagDom.d.ts +25 -0
  60. package/dist/types/ui/ContributorTag/contributorAvatarRenderer.d.ts +22 -0
  61. package/dist/types/ui/ContributorTag/contributorTagController.d.ts +85 -0
  62. package/dist/types/ui/ContributorTag/contributorTagIcons.d.ts +12 -0
  63. package/package.json +9 -13
  64. package/dist/cjs/ui/ContributorTag/ContributorTag.compiled.css +0 -29
  65. package/dist/cjs/ui/ContributorTag/ContributorTag.js +0 -383
  66. package/dist/cjs/ui/ContributorTag/ContributorTagWidget.js +0 -50
  67. package/dist/es2019/ui/ContributorTag/ContributorTag.compiled.css +0 -29
  68. package/dist/es2019/ui/ContributorTag/ContributorTag.js +0 -312
  69. package/dist/es2019/ui/ContributorTag/ContributorTagWidget.js +0 -43
  70. package/dist/esm/ui/ContributorTag/ContributorTag.compiled.css +0 -29
  71. package/dist/esm/ui/ContributorTag/ContributorTag.js +0 -375
  72. package/dist/esm/ui/ContributorTag/ContributorTagWidget.js +0 -43
  73. package/dist/types/ui/ContributorTag/ContributorTag.d.ts +0 -37
  74. package/dist/types/ui/ContributorTag/ContributorTagWidget.d.ts +0 -22
@@ -1,6 +1,8 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ import { PARTICIPANT_COLOR_SCHEMES } from './types';
5
+
4
6
  /** Green insertions, red deletions. */
5
7
  export var traditionalScheme = {
6
8
  insertColor: 'green',
@@ -64,30 +66,15 @@ var createAttributionScheme = function createAttributionScheme(color) {
64
66
  deletedCellColor: color
65
67
  });
66
68
  };
69
+ var attributionColorSchemes = Object.fromEntries(PARTICIPANT_COLOR_SCHEMES.map(function (color) {
70
+ return [color, createAttributionScheme(color)];
71
+ }));
67
72
 
68
73
  /** Maps public schemes and attribution-only participant slots to their data objects. */
69
- export var colorSchemeRegistry = {
70
- 'red-bolder': createAttributionScheme('red-bolder'),
71
- 'blue-bolder': createAttributionScheme('blue-bolder'),
72
- 'green-bolder': createAttributionScheme('green-bolder'),
73
- 'yellow-bolder': createAttributionScheme('yellow-bolder'),
74
- 'purple-bolder': createAttributionScheme('purple-bolder'),
75
- 'magenta-bolder': createAttributionScheme('magenta-bolder'),
76
- 'teal-bolder': createAttributionScheme('teal-bolder'),
77
- 'orange-bolder': createAttributionScheme('orange-bolder'),
78
- 'lime-bolder': createAttributionScheme('lime-bolder'),
79
- 'gray-bolder': createAttributionScheme('gray-bolder'),
80
- 'blue-subtle': createAttributionScheme('blue-subtle'),
81
- 'red-subtle': createAttributionScheme('red-subtle'),
82
- 'orange-subtle': createAttributionScheme('orange-subtle'),
83
- 'yellow-subtle': createAttributionScheme('yellow-subtle'),
84
- 'green-subtle': createAttributionScheme('green-subtle'),
85
- 'teal-subtle': createAttributionScheme('teal-subtle'),
86
- 'purple-subtle': createAttributionScheme('purple-subtle'),
87
- 'magenta-subtle': createAttributionScheme('magenta-subtle'),
74
+ export var colorSchemeRegistry = _objectSpread(_objectSpread({}, attributionColorSchemes), {}, {
88
75
  traditional: traditionalScheme,
89
76
  standard: standardScheme
90
- };
77
+ });
91
78
 
92
79
  /** Attribution accents are impossible in the refactor-off cohort; fall back defensively. */
93
80
  export var getLegacyColorScheme = function getLegacyColorScheme(colorScheme) {
@@ -1,16 +1,14 @@
1
1
  /** Schemes consumers may explicitly request through the show-diff API. */
2
2
 
3
3
  /** Attribution-only participant slots selected by the plugin, never by consumers. */
4
- export var PARTICIPANT_COLOR_SCHEMES = ['red-bolder', 'blue-bolder', 'green-bolder', 'yellow-bolder', 'purple-bolder', 'magenta-bolder', 'teal-bolder', 'orange-bolder', 'lime-bolder', 'gray-bolder', 'blue-subtle', 'red-subtle', 'orange-subtle', 'yellow-subtle', 'green-subtle', 'teal-subtle', 'purple-subtle', 'magenta-subtle'];
4
+ export var PARTICIPANT_COLOR_SCHEMES = ['red', 'blue', 'green', 'yellow', 'purple', 'magenta', 'teal', 'orange', 'lime', 'gray'];
5
5
 
6
6
  /** ADS accent hues used by the public and participant colour schemes. */
7
7
 
8
8
  /** A public scheme or an attribution participant slot resolved internally for one change. */
9
9
 
10
- /** A colour value that the factory expands into a complete set of diff-safe ADS tokens. */
11
-
12
10
  /**
13
- * A show-diff colour scheme. Colour fields are ADS hues or shared participant slots that
14
- * `factory.ts` expands into token paths; the rest encode structural differences no colour can
15
- * express. Ring widths, padding, radius and pointer-events are fixed in the factory, not per scheme.
11
+ * A show-diff colour scheme. Colour fields are ADS hues that `factory.ts` expands into token paths;
12
+ * the rest encode structural differences no colour can express. Ring widths, padding, radius and
13
+ * pointer-events are fixed in the factory, not per scheme.
16
14
  */
@@ -18,7 +18,6 @@ import { resolveCellOverlayStyleLegacy, resolveDeletedRowStyleLegacy } from './c
18
18
  import { buildDiffDecorationSpec } from './decorationKeys';
19
19
  import { findSafeInsertPos } from './utils/findSafeInsertPos';
20
20
  import { applyCellEdgeAttrs, getRowCellEdgeAttrs, getTableTopAndBottomCellEdgeAttrs } from './utils/tableCellEdgeAttrs';
21
- var DEFAULT_COLOR_SCHEME = 'standard';
22
21
  /**
23
22
  * Extracts information about deleted table rows from a change
24
23
  */
@@ -130,7 +129,7 @@ var isEmptyRow = function isEmptyRow(rowNode) {
130
129
  */
131
130
  var createChangedRowDOM = function createChangedRowDOM(rowNode, cellEdgeAttrs, nodeViewSerializer, colorScheme, isInserted, diffType) {
132
131
  var tr = document.createElement('tr');
133
- var colors = colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : DEFAULT_COLOR_SCHEME];
132
+ var colors = colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
134
133
 
135
134
  // Inserted rows keep their natural styling; the row strikethrough is deletions only.
136
135
  if (!isExtendedEnabled(diffType) || !isInserted) {
@@ -1,12 +1,11 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
- import { createElement } from 'react';
5
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
6
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
7
- import { ContributorTagWidget } from '../../ui/ContributorTag/ContributorTagWidget';
6
+ import { ContributorTagController } from '../../ui/ContributorTag/contributorTagController';
8
7
  import { clampAnchorPosIntoCell } from './createAnchorDecorationWidgets';
9
- import { buildContributorTagDecorationSpec, DecorationFamily } from './decorationKeys';
8
+ import { buildContributorTagDecorationSpec } from './decorationKeys';
10
9
 
11
10
  /** Marks the host element of one tag, so a tag can be found in the document by its own diff. */
12
11
  export var CONTRIBUTOR_TAG_HOST_ATTRIBUTE = 'data-contributor-tag-host';
@@ -17,23 +16,19 @@ var isContributorTagWidgetEnabled = function isContributorTagWidgetEnabled() {
17
16
  };
18
17
 
19
18
  /**
20
- * Everything a tag needs to mount itself into the document, plumbed down from the plugin. Absent in
19
+ * Everything a tag needs to draw itself into the document, plumbed down from the plugin. Absent in
21
20
  * unit tests that build decorations directly: the hosts are still emitted, they just stay empty.
22
21
  */
23
22
 
24
23
  /** A mounted tag, so whoever emitted the host can take it down again. */
25
24
 
26
25
  /**
27
- * Unique per mount rather than per diff, because ProseMirror draws a replacement widget before it
28
- * destroys the widget being replaced: on a shared key the outgoing widget's `destroy` would
29
- * unregister the incoming widget's portal.
30
- */
31
- var nextContributorTagPortalId = 0;
32
-
33
- /**
34
- * Renders the tag into `host` through the editor's portal provider, the way the rest of the editor
35
- * mounts React into decorations. The tag resolves its own model from plugin state, so a redraw of
36
- * the host re-parents the tag instead of stranding it, and `isActive` changes arrive as a re-render.
26
+ * Draws the tag into `host`. The tag resolves its own model from plugin state, so a redraw of the
27
+ * host re-parents the tag instead of stranding it, and `isActive` changes arrive as an update.
28
+ *
29
+ * Each mount owns its own controller and DOM, so when ProseMirror draws a replacement widget before
30
+ * destroying the one it replaces, the outgoing `destroy` cannot take the incoming tag down with it
31
+ * (EDITOR-8702).
37
32
  */
38
33
  export var mountContributorTag = function mountContributorTag(_ref) {
39
34
  var diffId = _ref.diffId,
@@ -42,24 +37,14 @@ export var mountContributorTag = function mountContributorTag(_ref) {
42
37
  if (!mountContext) {
43
38
  return undefined;
44
39
  }
45
- var api = mountContext.api,
46
- getEditorRoot = mountContext.getEditorRoot,
47
- portalProviderAPI = mountContext.portalProviderAPI;
48
- var key = "".concat(DecorationFamily.contributorTag, "-").concat(diffId, "-").concat(nextContributorTagPortalId++);
49
- portalProviderAPI.render(function () {
50
- return /*#__PURE__*/createElement(ContributorTagWidget, {
51
- api: api,
52
- diffId: diffId,
53
- getEditorRoot: getEditorRoot
54
- });
55
- }, host, key);
56
- return {
57
- key: key,
58
- portalProviderAPI: portalProviderAPI
59
- };
40
+ var controller = new ContributorTagController(_objectSpread(_objectSpread({}, mountContext), {}, {
41
+ diffId: diffId
42
+ }));
43
+ controller.mount(host);
44
+ return controller;
60
45
  };
61
46
  export var unmountContributorTag = function unmountContributorTag(mount) {
62
- mount === null || mount === void 0 || mount.portalProviderAPI.remove(mount.key);
47
+ mount === null || mount === void 0 || mount.destroy();
63
48
  };
64
49
 
65
50
  /**
@@ -15,9 +15,8 @@ import { buildDiffDecorationSpec } from './decorationKeys';
15
15
  var displayNoneStyle = convertToInlineCss({
16
16
  display: 'none'
17
17
  });
18
- var DEFAULT_COLOR_SCHEME = 'standard';
19
18
  var getColorScheme = function getColorScheme(colorScheme) {
20
- return colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : DEFAULT_COLOR_SCHEME];
19
+ return colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
21
20
  };
22
21
 
23
22
  /**
@@ -4,11 +4,9 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  import isEqual from 'lodash/isEqual';
5
5
  import omit from 'lodash/omit';
6
6
  import { SetAttrsStep } from '@atlaskit/adf-schema/steps/set-attrs';
7
- import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
8
7
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
9
8
  import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
10
9
  import { fg } from '@atlaskit/platform-feature-flags/fg';
11
- import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
12
10
  import { getRequiredIncludedDiffableAttrs, isDiffableAttr } from './diffableAttrs';
13
11
  var filterUndefined = function filterUndefined(x) {
14
12
  return !!x;
@@ -79,26 +77,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
79
77
  var nodeAtPos = doc.nodeAt(finalPos);
80
78
  var originalNodeAtPos = originalPos === undefined ? null : originalDoc.nodeAt(originalPos);
81
79
 
82
- // date node: timestamp attribute change — highlight the date node itself (inline)
83
- if (attrsToCheck.some(function (v) {
84
- return dateAttrs.includes(v);
85
- }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
86
- return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
87
- })) {
88
- return {
89
- fromB: finalPos,
90
- toB: finalPos + nodeAtPos.nodeSize,
91
- isInline: true,
92
- inlineNodeName: 'date'
93
- };
94
- }
95
-
96
- // The following inline node attr changes are gated behind platform_editor_improve_inline_diffs.
97
80
  // The changeset path (createDecorationsForChange) handles the deletion widget via
98
81
  // prosemirror-changeset; we only need to add the inline insertion highlight here.
99
- if (isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
100
- return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
101
- }) && nodeAtPos) {
82
+ if (nodeAtPos) {
102
83
  var nodeName = nodeAtPos.type.name;
103
84
  if (isInlineAttrChangeNodeName(nodeName)) {
104
85
  var watchedAttrs = inlineNodeAttrMap[nodeName];
@@ -175,12 +156,8 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
175
156
  // Deduplicate by node position: multiple AttrSteps on the same node
176
157
  // (e.g. setNodeAttribute(pos, 'text', ...) + setNodeAttribute(pos, 'color', ...))
177
158
  // should produce only one decoration, not one per step.
178
- // Gated behind the same experiment as the inline node attr changes that introduced
179
- // the possibility of multiple ranges for the same node position.
180
159
  .filter(function (range, i, arr) {
181
- return !isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
182
- return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
183
- }) || arr.findIndex(function (r) {
160
+ return arr.findIndex(function (r) {
184
161
  return r.fromB === range.fromB;
185
162
  }) === i;
186
163
  });
@@ -19,9 +19,8 @@ import { isExtendedEnabled } from '../../isExtendedEnabled';
19
19
  import { buildAddedCellOverlayRoundedStyle, buildAddedCellOverlayStyle, buildAddedCellOverlayStyleNew, buildDeletedCellOverlayRoundedStyle, buildDeletedCellOverlayStyle, buildDeletedInlineContentStyle, buildDeletedInlineContentStyleExtended, buildDeletedLozengeActiveStyle, buildDeletedLozengeStyle, buildDeletedNodeCSSVariables, buildDeletedQuoteNodeWithLozengeStyle, buildDeletedStrikethroughLine, buildDeletedWrappedBlockOutline, buildInsertedBlockNodeStyle, buildInsertedInlineStyle, buildInsertStyleInBlockExtended, buildInsertStyleInBlockExtendedNoUnderline, buildInsertStyleNode } from '../colorSchemes/factory';
20
20
  import { colorSchemeRegistry, getLegacyColorScheme, standardScheme } from '../colorSchemes/schemes';
21
21
  import { getChangedContentStyleLegacy, getChangedNodeStyleLegacy, getDeletedContentStyleLegacy, getDeletedContentStyleUnboundedLegacy, getInsertedContentStyleLegacy, hasRestingDeletedRingLegacy, resolveCellOverlayStyleLegacy, resolveNestedInsertedNodeStyleLegacy, resolveRemovedLozengeStyleLegacy } from './wrapBlockNodeViewStyles.legacy';
22
- var DEFAULT_COLOR_SCHEME = 'standard';
23
22
  var getColorScheme = function getColorScheme(colorScheme) {
24
- return colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : DEFAULT_COLOR_SCHEME];
23
+ return colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
25
24
  };
26
25
 
27
26
  /**
@@ -34,7 +34,7 @@ var dropOrphanedContributorTags = function dropOrphanedContributorTags(contribut
34
34
  });
35
35
  return liveTags.length === contributorTags.length ? contributorTags : liveTags;
36
36
  };
37
- export var createPlugin = function createPlugin(config, getIntl, api, portalProviderAPI, onEditorView) {
37
+ export var createPlugin = function createPlugin(config, getIntl, api, onEditorView) {
38
38
  enforceCustomStepRegisters();
39
39
  var nodeViewSerializer = new NodeViewSerializer({});
40
40
  var setNodeViewSerializer = function setNodeViewSerializer(editorView) {
@@ -51,14 +51,14 @@ export var createPlugin = function createPlugin(config, getIntl, api, portalProv
51
51
  * lifecycle, which decorations are calculated independently of.
52
52
  */
53
53
  var currentEditorView;
54
- var tagMountContext = portalProviderAPI ? {
54
+ var tagMountContext = {
55
55
  api: api,
56
56
  getEditorRoot: function getEditorRoot() {
57
57
  var _currentEditorView$do, _currentEditorView;
58
58
  return (_currentEditorView$do = (_currentEditorView = currentEditorView) === null || _currentEditorView === void 0 ? void 0 : _currentEditorView.dom) !== null && _currentEditorView$do !== void 0 ? _currentEditorView$do : null;
59
59
  },
60
- portalProviderAPI: portalProviderAPI
61
- } : undefined;
60
+ getIntl: getIntl
61
+ };
62
62
  return new SafePlugin({
63
63
  key: showDiffPluginKey,
64
64
  state: {
@@ -98,12 +98,11 @@ export var showDiffPlugin = function showDiffPlugin(_ref3) {
98
98
  pmPlugins: function pmPlugins() {
99
99
  return [{
100
100
  name: 'showDiffPlugin',
101
- // Contributor tags mount into their own decoration widgets through the portal
102
- // provider, the way the rest of the editor renders React into decorations.
101
+ // Contributor tags draw themselves into their own decoration widgets — plain DOM, so
102
+ // no portal provider is needed here.
103
103
  plugin: function plugin(_ref8) {
104
- var getIntl = _ref8.getIntl,
105
- nodeViewPortalProviderAPI = _ref8.nodeViewPortalProviderAPI;
106
- return createPlugin(config, getIntl, api, nodeViewPortalProviderAPI, setEditorView);
104
+ var getIntl = _ref8.getIntl;
105
+ return createPlugin(config, getIntl, api, setEditorView);
107
106
  }
108
107
  }];
109
108
  },
@@ -0,0 +1,115 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
3
+ export var CONTRIBUTOR_TAG_TESTID = 'diff-contributor-tag';
4
+ export var CONTRIBUTOR_TAG_NAME_TESTID = 'diff-contributor-tag-name';
5
+
6
+ /**
7
+ * Floor for the tag width (~one 16px avatar plus padding), so the highlight-width clamp cannot
8
+ * collapse the box on a very short highlight.
9
+ */
10
+ export var MIN_TAG_WIDTH = '28px';
11
+
12
+ // Positioned against the host widget its decoration renders on the change's first character:
13
+ // `bottom: 100%` lifts the tag onto the line above, `inset-inline-start` starts it on that
14
+ // character.
15
+ var constraintStyle = convertToInlineCss({
16
+ display: 'block',
17
+ position: 'absolute',
18
+ bottom: '100%',
19
+ insetInlineStart: 0,
20
+ minWidth: 0,
21
+ // The tag may cover surrounding text, so it has to paint over it. Matches `akEditorUnitZIndex`.
22
+ zIndex: 1,
23
+ // It renders inside the document and it is not content: dragging a selection across the change
24
+ // must not select it.
25
+ userSelect: 'none'
26
+ });
27
+
28
+ // `backgroundColor`, `borderBottomColor` and the visibility come from the model, and are set by the
29
+ // controller.
30
+ var tagStyle = convertToInlineCss({
31
+ display: 'inline-flex',
32
+ alignItems: 'center',
33
+ gap: "var(--ds-space-050, 4px)",
34
+ // Never wider than the highlight; overflow is ellipsised on the name below.
35
+ maxWidth: '100%',
36
+ minWidth: 0,
37
+ overflow: 'hidden',
38
+ paddingInline: "var(--ds-space-050, 4px)",
39
+ paddingBlock: "var(--ds-space-025, 2px)",
40
+ borderRadius: "var(--ds-radius-small, 4px)",
41
+ borderBottomStyle: 'solid',
42
+ borderBottomWidth: "var(--ds-border-width-selected, 2px)",
43
+ boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)",
44
+ font: "var(--ds-font-body-small, normal 400 12px/16px \"Atlassian Sans\", ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
45
+ whiteSpace: 'nowrap',
46
+ boxSizing: 'border-box'
47
+ });
48
+ var avatarsStyle = convertToInlineCss({
49
+ display: 'inline-flex',
50
+ alignItems: 'center',
51
+ flexShrink: 0
52
+ });
53
+ var nameStyle = convertToInlineCss({
54
+ display: 'block',
55
+ minWidth: 0,
56
+ overflow: 'hidden',
57
+ textOverflow: 'ellipsis',
58
+ whiteSpace: 'nowrap'
59
+ });
60
+
61
+ /** `@atlaskit/visually-hidden`, inlined. */
62
+ var srLabelStyle = convertToInlineCss({
63
+ width: '1px',
64
+ height: '1px',
65
+ padding: 0,
66
+ position: 'absolute',
67
+ border: 0,
68
+ clip: 'rect(1px, 1px, 1px, 1px)',
69
+ overflow: 'hidden',
70
+ userSelect: 'none',
71
+ whiteSpace: 'nowrap'
72
+ });
73
+ var createSpan = function createSpan(doc, style) {
74
+ var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
75
+ var span = doc.createElement('span');
76
+ span.setAttribute('style', style);
77
+ for (var _i = 0, _Object$entries = Object.entries(attributes); _i < _Object$entries.length; _i++) {
78
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
79
+ name = _Object$entries$_i[0],
80
+ value = _Object$entries$_i[1];
81
+ span.setAttribute(name, value);
82
+ }
83
+ return span;
84
+ };
85
+ /**
86
+ * The tag's markup, with no model applied — see `ContributorTagController`.
87
+ *
88
+ * Built element by element rather than through `DOMSerializer.renderSpec`, which returns `Node` and
89
+ * would need a cast per reference below.
90
+ */
91
+ export var buildContributorTagDom = function buildContributorTagDom(doc) {
92
+ var root = createSpan(doc, constraintStyle);
93
+ var tag = createSpan(doc, tagStyle, {
94
+ 'data-testid': CONTRIBUTOR_TAG_TESTID,
95
+ // Deliberately no `aria-label`: it would be announced ahead of the element's contents, but
96
+ // design requires the contributor *after* the change — hence the visually hidden label.
97
+ role: 'note',
98
+ // Focusable so keyboard and screen-reader users can reach the tag and its tooltip.
99
+ tabindex: '0'
100
+ });
101
+ var avatars = createSpan(doc, avatarsStyle);
102
+ var name = createSpan(doc, nameStyle, {
103
+ 'data-testid': CONTRIBUTOR_TAG_NAME_TESTID
104
+ });
105
+ var srLabel = createSpan(doc, srLabelStyle);
106
+ tag.append(avatars, name, srLabel);
107
+ root.appendChild(tag);
108
+ return {
109
+ avatars: avatars,
110
+ name: name,
111
+ root: root,
112
+ srLabel: srLabel,
113
+ tag: tag
114
+ };
115
+ };
@@ -0,0 +1,135 @@
1
+ import { bind } from 'bind-event-listener';
2
+ import { AVATAR_SIZES } from '@atlaskit/avatar/avatar-sizes';
3
+ import { BORDER_WIDTH } from '@atlaskit/avatar/constants/default';
4
+ import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
5
+ import { getContributorTagIcon } from './contributorTagIcons';
6
+
7
+ /** The size `@atlaskit/avatar`'s `xxsmall` rendered at. */
8
+ var AVATAR_SIZE = AVATAR_SIZES.xxsmall;
9
+ /** `xxsmall` also carried a `space.025` margin — the same 2px — which is where the ring is painted. */
10
+ var AVATAR_RING_WIDTH = BORDER_WIDTH;
11
+ var AVATAR_BOX_SIZE = AVATAR_SIZE + AVATAR_RING_WIDTH * 2;
12
+
13
+ /** Reused from `@atlaskit/avatar`'s `avatar-content`, so the two shapes cannot drift. */
14
+ var HEXAGON_CLIP_PATH = 'polygon(45% 1.33975%, 46.5798% 0.60307%, 48.26352% 0.15192%, 50% 0%, 51.73648% 0.15192%, 53.4202% 0.60307%, 55% 1.33975%, 89.64102% 21.33975%, 91.06889% 22.33956%, 92.30146% 23.57212%, 93.30127% 25%, 94.03794% 26.5798%, 94.48909% 28.26352%, 94.64102% 30%, 94.64102% 70%, 94.48909% 71.73648%, 94.03794% 73.4202%, 93.30127% 75%, 92.30146% 76.42788%, 91.06889% 77.66044%, 89.64102% 78.66025%, 55% 98.66025%, 53.4202% 99.39693%, 51.73648% 99.84808%, 50% 100%, 48.26352% 99.84808%, 46.5798% 99.39693%, 45% 98.66025%, 10.35898% 78.66025%, 8.93111% 77.66044%, 7.69854% 76.42788%, 6.69873% 75%, 5.96206% 73.4202%, 5.51091% 71.73648%, 5.35898% 70%, 5.35898% 30%, 5.51091% 28.26352%, 5.96206% 26.5798%, 6.69873% 25%, 7.69854% 23.57212%, 8.93111% 22.33956%, 10.35898% 21.33975%)';
15
+ var boxStyle = convertToInlineCss({
16
+ display: 'inline-flex',
17
+ alignItems: 'center',
18
+ justifyContent: 'center',
19
+ flexShrink: 0,
20
+ boxSizing: 'border-box',
21
+ width: "".concat(AVATAR_BOX_SIZE, "px"),
22
+ height: "".concat(AVATAR_BOX_SIZE, "px")
23
+ });
24
+ var shapeStyle = convertToInlineCss({
25
+ display: 'inline-flex',
26
+ alignItems: 'center',
27
+ justifyContent: 'center',
28
+ boxSizing: 'border-box',
29
+ width: "".concat(AVATAR_SIZE, "px"),
30
+ height: "".concat(AVATAR_SIZE, "px"),
31
+ overflow: 'hidden'
32
+ });
33
+ var imageStyle = convertToInlineCss({
34
+ display: 'block',
35
+ width: '100%',
36
+ height: '100%',
37
+ objectFit: 'cover'
38
+ });
39
+
40
+ /** The `@atlaskit/avatar` image fallback: a subtle glyph on a tinted box. */
41
+ var personFallbackStyle = convertToInlineCss({
42
+ width: '100%',
43
+ height: '100%',
44
+ display: 'flex',
45
+ alignItems: 'center',
46
+ justifyContent: 'center',
47
+ backgroundColor: "var(--ds-background-accent-gray-subtler, #DDDEE1)",
48
+ color: "var(--ds-icon-subtle, #505258)"
49
+ });
50
+ /**
51
+ * One 16px avatar for a contributor: a circle for a person, a hexagon for an agent.
52
+ *
53
+ * Mirrors `mentionAvatarRenderer` — a bare `<img>` with a glyph fallback bound to `error`, and the
54
+ * hexagon cut with `clip-path`. The ring `@atlaskit/avatar` drew from `borderColor` is a
55
+ * `box-shadow` on the circle and a second clipped hexagon behind the agent, since `box-shadow` is
56
+ * cut away by `clip-path`.
57
+ */
58
+ export var contributorAvatarRenderer = function contributorAvatarRenderer(_ref) {
59
+ var contributor = _ref.contributor,
60
+ doc = _ref.doc,
61
+ ringColor = _ref.ringColor,
62
+ stackIndex = _ref.stackIndex;
63
+ var isAgent = contributor.kind === 'agent';
64
+ var element = doc.createElement('span');
65
+ element.setAttribute('style', boxStyle);
66
+ // Decorative: the tag names its contributors in the visually hidden label its screen-reader
67
+ // announcement comes from.
68
+ element.setAttribute('aria-hidden', 'true');
69
+ if (stackIndex !== undefined) {
70
+ element.style.setProperty('z-index', String(stackIndex));
71
+ }
72
+ var shape = doc.createElement('span');
73
+ shape.setAttribute('style', shapeStyle);
74
+ element.appendChild(shape);
75
+ if (isAgent) {
76
+ element.style.setProperty('clip-path', HEXAGON_CLIP_PATH);
77
+ shape.style.setProperty('clip-path', HEXAGON_CLIP_PATH);
78
+ } else {
79
+ shape.style.setProperty('border-radius', "var(--ds-radius-full, 9999px)");
80
+ }
81
+ var image;
82
+ var unbindImageError;
83
+ var showFallback = function showFallback() {
84
+ var _unbindImageError, _image;
85
+ (_unbindImageError = unbindImageError) === null || _unbindImageError === void 0 || _unbindImageError();
86
+ unbindImageError = undefined;
87
+ (_image = image) === null || _image === void 0 || _image.remove();
88
+ image = undefined;
89
+ if (!isAgent) {
90
+ var fallback = doc.createElement('span');
91
+ fallback.setAttribute('style', personFallbackStyle);
92
+ fallback.appendChild(getContributorTagIcon('person', doc));
93
+ shape.appendChild(fallback);
94
+ return;
95
+ }
96
+ shape.appendChild(getContributorTagIcon(contributor.agentKind === 'rovo' ? 'rovoHex' : 'aiBot', doc));
97
+ };
98
+ if (contributor.avatarUrl) {
99
+ image = doc.createElement('img');
100
+ image.alt = '';
101
+ image.decoding = 'async';
102
+ image.draggable = false;
103
+ image.loading = 'lazy';
104
+ image.setAttribute('style', imageStyle);
105
+ unbindImageError = bind(image, {
106
+ type: 'error',
107
+ listener: showFallback
108
+ });
109
+ shape.appendChild(image);
110
+ image.src = contributor.avatarUrl;
111
+ } else {
112
+ showFallback();
113
+ }
114
+ var setRingColor = function setRingColor(nextRingColor) {
115
+ if (isAgent) {
116
+ element.style.setProperty('background', nextRingColor);
117
+ // Shows through wherever the artwork is transparent, as the avatar background did.
118
+ shape.style.setProperty('background', nextRingColor);
119
+ return;
120
+ }
121
+ shape.style.setProperty('box-shadow', "0 0 0 ".concat(AVATAR_RING_WIDTH, "px ").concat(nextRingColor));
122
+ shape.style.setProperty('background', nextRingColor);
123
+ };
124
+ setRingColor(ringColor);
125
+ return {
126
+ destroy: function destroy() {
127
+ var _unbindImageError2;
128
+ (_unbindImageError2 = unbindImageError) === null || _unbindImageError2 === void 0 || _unbindImageError2();
129
+ unbindImageError = undefined;
130
+ element.remove();
131
+ },
132
+ element: element,
133
+ setRingColor: setRingColor
134
+ };
135
+ };