@atlaskit/editor-plugin-show-diff 30.0.10 → 30.0.12

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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 30.0.12
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ba8362b562ea6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ba8362b562ea6) -
8
+ EDITOR-10060 Renders the human avatar in a connected agent+human contributor tag 4px smaller
9
+ (12px) and overlapping the agent icon, instead of sitting flush beside it.
10
+ - Updated dependencies
11
+
12
+ ## 30.0.11
13
+
14
+ ### Patch Changes
15
+
16
+ - [`4ad02bd627f7f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4ad02bd627f7f) -
17
+ Respect explicit brand active colours and otherwise use the existing gray active diff treatment.
18
+ Preserve Rovo purple active colours and Claude specified light and dark colours. Route contributor
19
+ attribution through shared brand schemes under platform_editor_attributed_version_history,
20
+ platform_editor_show_diff_color_scheme_refactor, platform_editor_agent_mentions and
21
+ platform_editor_agent_telepointer_redesign.
22
+ - Updated dependencies
23
+
3
24
  ## 30.0.10
4
25
 
5
26
  ### Patch Changes
@@ -28,8 +28,8 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
28
28
  var HASHED_PARTICIPANT_COLOR_SCHEMES = [].concat((0, _toConsumableArray2.default)(_types.PARTICIPANT_COLOR_SCHEMES), ['blue', 'red', 'orange', 'yellow', 'green', 'teal', 'purple', 'magenta']);
29
29
 
30
30
  /**
31
- * Red means "deleted" in both public schemes, so it never identifies an actor. Reserving it here
32
- * covers every path into an attribution colour; `createAttributionColorMap` is the only caller, and
31
+ * ADS red means "deleted" in both public schemes, so it is excluded from hashed participant colours.
32
+ * Brand schemes retain their own palettes. `createAttributionColorMap` is the only caller, and
33
33
  * it is gated on `platform_editor_attributed_version_history` plus
34
34
  * `platform_editor_show_diff_color_scheme_refactor`.
35
35
  */
@@ -142,23 +142,25 @@ var isContributorTagsEnabled = exports.isContributorTagsEnabled = function isCon
142
142
  })) && contributors !== undefined && Object.keys(contributors).length > 0;
143
143
  };
144
144
  var getAttributionParticipantColor = function getAttributionParticipantColor(attribution, identity, contributors) {
145
- var _ref2, _getThirdPartyAgentCo, _attribution$agentId2;
145
+ var _ref2, _attribution$agentId2;
146
146
  var contributor = contributors === null || contributors === void 0 ? void 0 : contributors[identity.key];
147
147
  var brand = isDiffAgentBrand(contributor === null || contributor === void 0 ? void 0 : contributor.agentKind) ? contributor === null || contributor === void 0 ? void 0 : contributor.agentKind : undefined;
148
- var agentName = (_ref2 = brand !== null && brand !== void 0 ? brand : (_getThirdPartyAgentCo = (0, _getThirdPartyAgentColor.getThirdPartyAgentColor)({
149
- agentNamedId: attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId,
150
- agentName: contributor === null || contributor === void 0 ? void 0 : contributor.name
151
- })) === null || _getThirdPartyAgentCo === void 0 ? void 0 : _getThirdPartyAgentCo.name) !== null && _ref2 !== void 0 ? _ref2 : attribution !== null && attribution !== void 0 && (_attribution$agentId2 = attribution.agentId) !== null && _attribution$agentId2 !== void 0 && _attribution$agentId2.trim() ? (contributor === null || contributor === void 0 ? void 0 : contributor.name) || 'Agent' : undefined;
152
- return (0, _utils.getParticipantColor)(identity.colorSeed, agentName,
148
+ var brandColor = (0, _getThirdPartyAgentColor.getThirdPartyAgentColor)({
149
+ agentNamedId: brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId,
150
+ agentName: brand !== null && brand !== void 0 ? brand : contributor === null || contributor === void 0 ? void 0 : contributor.name
151
+ });
152
+ var agentName = (_ref2 = brand !== null && brand !== void 0 ? brand : brandColor === null || brandColor === void 0 ? void 0 : brandColor.name) !== null && _ref2 !== void 0 ? _ref2 : attribution !== null && attribution !== void 0 && (_attribution$agentId2 = attribution.agentId) !== null && _attribution$agentId2 !== void 0 && _attribution$agentId2.trim() ? (contributor === null || contributor === void 0 ? void 0 : contributor.name) || 'Agent' : undefined;
153
+ return _objectSpread(_objectSpread({}, (0, _utils.getParticipantColor)(identity.colorSeed, agentName,
153
154
  // Keep an explicitly resolved brand consistent with the contributor's icon.
154
- brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId);
155
+ brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId)), {}, {
156
+ scheme: brandColor === null || brandColor === void 0 ? void 0 : brandColor.scheme
157
+ });
155
158
  };
156
159
  var createAttributionColorMap = exports.createAttributionColorMap = function createAttributionColorMap(stepAttributions, contributors) {
157
160
  var colors = new Map();
158
161
  var allocatedColors = new Set();
159
162
 
160
- // Reserve shared brand colours before hashing other actors, regardless of step order. A brand
161
- // slot is pinned deliberately, so it is taken verbatim rather than through `getSlotColor`.
163
+ // Keep brand schemes intact; only unbranded contributors use the hashed ADS palette below.
162
164
  var _iterator2 = _createForOfIteratorHelper(stepAttributions),
163
165
  _step2;
164
166
  try {
@@ -170,10 +172,14 @@ var createAttributionColorMap = exports.createAttributionColorMap = function cre
170
172
  }
171
173
  var _getAttributionPartic = getAttributionParticipantColor(attribution, identity, contributors),
172
174
  index = _getAttributionPartic.index,
173
- isFixed = _getAttributionPartic.isFixed;
175
+ isFixed = _getAttributionPartic.isFixed,
176
+ scheme = _getAttributionPartic.scheme;
177
+ if (scheme) {
178
+ colors.set(identity.key, scheme);
179
+ }
180
+ // Keep the old slot reserved so selecting a brand cannot recolour other contributors.
174
181
  var color = HASHED_PARTICIPANT_COLOR_SCHEMES[index];
175
182
  if (isFixed && color) {
176
- colors.set(identity.key, color);
177
183
  allocatedColors.add(color);
178
184
  }
179
185
  }
@@ -221,8 +221,8 @@ function bgBolder(color) {
221
221
  return (_getBrand$bold = (_getBrand4 = getBrand(color)) === null || _getBrand4 === void 0 ? void 0 : _getBrand4.bold) !== null && _getBrand$bold !== void 0 ? _getBrand$bold : bgBolderMap[color];
222
222
  }
223
223
  function bgSubtlerPressed(color) {
224
- var _getBrand$background3, _getBrand5;
225
- return (_getBrand$background3 = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.background) !== null && _getBrand$background3 !== void 0 ? _getBrand$background3 : bgSubtlerPressedMap[color];
224
+ var _ref, _getBrand$emphasisBac, _getBrand5;
225
+ return (_ref = (_getBrand$emphasisBac = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlerPressedMap[color]) !== null && _ref !== void 0 ? _ref : bgSubtlerPressedMap.gray;
226
226
  }
227
227
  function borderAccent(color) {
228
228
  var _getBrand$border2, _getBrand6;
@@ -233,8 +233,8 @@ function textAccent(color) {
233
233
  return (_getBrand$accentText = (_getBrand7 = getBrand(color)) === null || _getBrand7 === void 0 ? void 0 : _getBrand7.accentText) !== null && _getBrand$accentText !== void 0 ? _getBrand$accentText : textAccentMap[color];
234
234
  }
235
235
  function deletedBackground(color) {
236
- var _getBrand$emphasisBac, _getBrand8;
237
- return (_getBrand$emphasisBac = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlest(color);
236
+ var _getBrand$emphasisBac2, _getBrand8;
237
+ return (_getBrand$emphasisBac2 = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac2 !== void 0 ? _getBrand$emphasisBac2 : bgSubtlest(color);
238
238
  }
239
239
 
240
240
  /** Contributor tags use a bold fill with a contrasting foreground, including branded schemes. */
@@ -316,13 +316,14 @@ function buildInsertStyleInBlockExtended(colors) {
316
316
 
317
317
  /** Active state of the extended insert style. */
318
318
  function buildInsertStyleExtendedActive(colors) {
319
+ var _ref2, _brand$activeBorder;
319
320
  var brand = getBrand(colors.insertColor);
320
321
  return (0, _cssHelper.convertToInlineCss)(_objectSpread(_objectSpread({
321
322
  background: bgSubtlerPressed(colors.insertActiveColor)
322
323
  }, brand ? {
323
324
  color: brand.text
324
325
  } : {}), {}, {
325
- borderBottom: "2px solid ".concat(borderAccent(colors.insertColor)),
326
+ borderBottom: "2px solid ".concat((_ref2 = (_brand$activeBorder = brand === null || brand === void 0 ? void 0 : brand.activeBorder) !== null && _brand$activeBorder !== void 0 ? _brand$activeBorder : borderAccentMap[colors.insertColor]) !== null && _ref2 !== void 0 ? _ref2 : borderAccentMap.gray),
326
327
  padding: "1px 0 2px"
327
328
  }));
328
329
  }
@@ -1117,9 +1118,9 @@ function buildDeletedQuoteNodeWithLozengeStyle(colors, isActive) {
1117
1118
  * codeBlock). Every scheme shares the active state; `deletedNodeEmphasis` changes only the
1118
1119
  * resting one — 'stateful' a 4px subtlest ring, 'static' a 1px accent ring.
1119
1120
  */
1120
- function buildDeletedWrappedBlockOutline(colors, _ref) {
1121
- var isActive = _ref.isActive,
1122
- isRounded = _ref.isRounded;
1121
+ function buildDeletedWrappedBlockOutline(colors, _ref3) {
1122
+ var isActive = _ref3.isActive,
1123
+ isRounded = _ref3.isRounded;
1123
1124
  if (isActive) {
1124
1125
  return isRounded ? buildDeletedBlockOutlineRoundedActive(colors) : buildDeletedBlockOutlineActive(colors);
1125
1126
  }
@@ -13,40 +13,35 @@ var _contributorTagIcons = require("./contributorTagIcons");
13
13
  var AVATAR_SIZE = _avatarSizes.AVATAR_SIZES.xxsmall;
14
14
  /** `xxsmall` also carried a `space.025` margin — the same 2px — which is where the ring is painted. */
15
15
  var AVATAR_RING_WIDTH = _default.BORDER_WIDTH;
16
- var AVATAR_BOX_SIZE = AVATAR_SIZE + AVATAR_RING_WIDTH * 2;
17
16
 
18
17
  /** Reused from `@atlaskit/avatar`'s `avatar-content`, so the two shapes cannot drift. */
19
18
  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%)';
20
- var boxStyle = (0, _cssHelper.convertToInlineCss)({
21
- display: 'inline-flex',
22
- alignItems: 'center',
23
- justifyContent: 'center',
24
- flexShrink: 0,
25
- boxSizing: 'border-box',
26
- width: "".concat(AVATAR_BOX_SIZE, "px"),
27
- height: "".concat(AVATAR_BOX_SIZE, "px")
28
- });
29
19
 
30
- /** Agents get a drop shadow instead of a ring, so their box skips the ring's padding. */
31
- var agentBoxStyle = (0, _cssHelper.convertToInlineCss)({
32
- display: 'inline-flex',
33
- alignItems: 'center',
34
- justifyContent: 'center',
35
- flexShrink: 0,
36
- boxSizing: 'border-box',
37
- width: "".concat(AVATAR_SIZE, "px"),
38
- height: "".concat(AVATAR_SIZE, "px")
39
- });
40
- var shapeStyle = (0, _cssHelper.convertToInlineCss)({
41
- display: 'flex',
42
- alignItems: 'center',
43
- justifyContent: 'center',
44
- boxSizing: 'border-box',
45
- width: "".concat(AVATAR_SIZE, "px"),
46
- height: "".concat(AVATAR_SIZE, "px"),
47
- aspectRatio: '1/1',
48
- overflow: 'hidden'
49
- });
20
+ /** The avatar plus its ring. */
21
+ var getBoxStyle = function getBoxStyle(size, ringWidth) {
22
+ var boxSize = size + ringWidth * 2;
23
+ return (0, _cssHelper.convertToInlineCss)({
24
+ display: 'inline-flex',
25
+ alignItems: 'center',
26
+ justifyContent: 'center',
27
+ flexShrink: 0,
28
+ boxSizing: 'border-box',
29
+ width: "".concat(boxSize, "px"),
30
+ height: "".concat(boxSize, "px")
31
+ });
32
+ };
33
+ var getShapeStyle = function getShapeStyle(size) {
34
+ return (0, _cssHelper.convertToInlineCss)({
35
+ display: 'flex',
36
+ alignItems: 'center',
37
+ justifyContent: 'center',
38
+ boxSizing: 'border-box',
39
+ width: "".concat(size, "px"),
40
+ height: "".concat(size, "px"),
41
+ aspectRatio: '1/1',
42
+ overflow: 'hidden'
43
+ });
44
+ };
50
45
 
51
46
  /**
52
47
  * The shadow's colour per theme. In the dark theme `elevation.shadow.overflow.perimeter` is
@@ -88,10 +83,16 @@ var contributorAvatarRenderer = exports.contributorAvatarRenderer = function con
88
83
  var contributor = _ref.contributor,
89
84
  doc = _ref.doc,
90
85
  ringColor = _ref.ringColor,
86
+ _ref$ringWidth = _ref.ringWidth,
87
+ ringWidth = _ref$ringWidth === void 0 ? AVATAR_RING_WIDTH : _ref$ringWidth,
88
+ _ref$size = _ref.size,
89
+ size = _ref$size === void 0 ? AVATAR_SIZE : _ref$size,
91
90
  stackIndex = _ref.stackIndex;
92
91
  var isAgent = contributor.kind === 'agent';
93
92
  var element = doc.createElement('span');
94
- element.setAttribute('style', isAgent ? "".concat(agentBoxStyle, " ").concat(agentShadowStyle) : boxStyle);
93
+ // Agents get a drop shadow instead of a ring, so their box skips the ring's padding.
94
+ var boxStyle = getBoxStyle(size, isAgent ? 0 : ringWidth);
95
+ element.setAttribute('style', isAgent ? "".concat(boxStyle, " ").concat(agentShadowStyle) : boxStyle);
95
96
  // Decorative: the tag names its contributors in the visually hidden label its screen-reader
96
97
  // announcement comes from.
97
98
  element.setAttribute('aria-hidden', 'true');
@@ -99,7 +100,7 @@ var contributorAvatarRenderer = exports.contributorAvatarRenderer = function con
99
100
  element.style.setProperty('z-index', String(stackIndex));
100
101
  }
101
102
  var shape = doc.createElement('span');
102
- shape.setAttribute('style', shapeStyle);
103
+ shape.setAttribute('style', getShapeStyle(size));
103
104
  element.appendChild(shape);
104
105
  if (isAgent) {
105
106
  shape.style.setProperty('clip-path', HEXAGON_CLIP_PATH);
@@ -145,7 +146,7 @@ var contributorAvatarRenderer = exports.contributorAvatarRenderer = function con
145
146
  shape.style.setProperty('background', nextRingColor);
146
147
  return;
147
148
  }
148
- shape.style.setProperty('box-shadow', "0 0 0 ".concat(AVATAR_RING_WIDTH, "px ").concat(nextRingColor));
149
+ shape.style.setProperty('box-shadow', "0 0 0 ".concat(ringWidth, "px ").concat(nextRingColor));
149
150
  shape.style.setProperty('background', nextRingColor);
150
151
  };
151
152
  setRingColor(ringColor);
@@ -32,6 +32,13 @@ var getTagAccent = function getTagAccent(_ref) {
32
32
  return (0, _factory.getAccentTokens)(accent);
33
33
  };
34
34
 
35
+ /** Person's diameter in a connected pair. */
36
+ var CONNECTED_USER_AVATAR_SIZE = 12;
37
+ /** Px the person overlaps the agent. */
38
+ var CONNECTED_AVATAR_OVERLAP = 3;
39
+ /** Px of ring around the person in a connected pair. */
40
+ var CONNECTED_USER_RING_WIDTH = 1;
41
+
35
42
  /** Bespoke accents for agent kinds that use standard ADS tokens rather than the agent-color registry. */
36
43
  var BESPOKE_AGENT_ACCENTS = {
37
44
  rovo: {
@@ -342,29 +349,34 @@ var ContributorTagController = exports.ContributorTagController = /*#__PURE__*/f
342
349
  var agent = isPrimaryAgent ? model.contributor : model.connectedContributor;
343
350
 
344
351
  // Hand-rolled avatar stack: `@atlaskit/avatar-group` cannot render below 24px and the tag uses
345
- // 16px avatars.
352
+ // 16px avatars. A connected pair's person is smaller and overlaps the agent.
346
353
  var stack = model.connectedContributor ? [].concat((0, _toConsumableArray2.default)(agent ? [{
347
354
  contributor: agent,
348
- stackIndex: 1
355
+ stackIndex: 0
349
356
  }] : []), (0, _toConsumableArray2.default)(user ? [{
350
357
  contributor: user,
351
- stackIndex: 0
358
+ ringWidth: CONNECTED_USER_RING_WIDTH,
359
+ size: CONNECTED_USER_AVATAR_SIZE,
360
+ stackIndex: 1
352
361
  }] : [])) : [{
353
362
  contributor: model.contributor
354
363
  }];
355
364
  stack.forEach(function (_ref6, index) {
356
365
  var contributor = _ref6.contributor,
366
+ ringWidth = _ref6.ringWidth,
367
+ size = _ref6.size,
357
368
  stackIndex = _ref6.stackIndex;
358
369
  var avatar = (0, _contributorAvatarRenderer.contributorAvatarRenderer)({
359
370
  contributor: contributor,
360
371
  doc: doc,
361
372
  ringColor: background,
373
+ ringWidth: ringWidth,
374
+ size: size,
362
375
  stackIndex: stackIndex
363
376
  });
364
377
  if (index < stack.length - 1) {
365
- // Sits the leading avatar of a connected pair flush against the one behind it, with
366
- // no overlap and no extra gap.
367
- avatar.element.style.setProperty('margin-inline-end', '0');
378
+ // The person's ring cuts a gap into the agent.
379
+ avatar.element.style.setProperty('margin-inline-end', "-".concat(CONNECTED_AVATAR_OVERLAP, "px"));
368
380
  }
369
381
  container.appendChild(avatar.element);
370
382
  _this5.avatars.push(avatar);
@@ -12,8 +12,8 @@ import { PARTICIPANT_COLOR_SCHEMES } from './types';
12
12
  const HASHED_PARTICIPANT_COLOR_SCHEMES = [...PARTICIPANT_COLOR_SCHEMES, 'blue', 'red', 'orange', 'yellow', 'green', 'teal', 'purple', 'magenta'];
13
13
 
14
14
  /**
15
- * Red means "deleted" in both public schemes, so it never identifies an actor. Reserving it here
16
- * covers every path into an attribution colour; `createAttributionColorMap` is the only caller, and
15
+ * ADS red means "deleted" in both public schemes, so it is excluded from hashed participant colours.
16
+ * Brand schemes retain their own palettes. `createAttributionColorMap` is the only caller, and
17
17
  * it is gated on `platform_editor_attributed_version_history` plus
18
18
  * `platform_editor_show_diff_color_scheme_refactor`.
19
19
  */
@@ -109,23 +109,26 @@ export const isAttributionColoringEnabled = stepAttributions => {
109
109
  */
110
110
  export const isContributorTagsEnabled = (stepAttributions, contributors) => areAttributionColorGatesEnabled() && Boolean(stepAttributions === null || stepAttributions === void 0 ? void 0 : stepAttributions.some(attribution => getAttributionKey(attribution) !== undefined)) && contributors !== undefined && Object.keys(contributors).length > 0;
111
111
  const getAttributionParticipantColor = (attribution, identity, contributors) => {
112
- var _ref, _getThirdPartyAgentCo, _attribution$agentId2;
112
+ var _ref, _attribution$agentId2;
113
113
  const contributor = contributors === null || contributors === void 0 ? void 0 : contributors[identity.key];
114
114
  const brand = isDiffAgentBrand(contributor === null || contributor === void 0 ? void 0 : contributor.agentKind) ? contributor === null || contributor === void 0 ? void 0 : contributor.agentKind : undefined;
115
- const agentName = (_ref = brand !== null && brand !== void 0 ? brand : (_getThirdPartyAgentCo = getThirdPartyAgentColor({
116
- agentNamedId: attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId,
117
- agentName: contributor === null || contributor === void 0 ? void 0 : contributor.name
118
- })) === null || _getThirdPartyAgentCo === void 0 ? void 0 : _getThirdPartyAgentCo.name) !== null && _ref !== void 0 ? _ref : attribution !== null && attribution !== void 0 && (_attribution$agentId2 = attribution.agentId) !== null && _attribution$agentId2 !== void 0 && _attribution$agentId2.trim() ? (contributor === null || contributor === void 0 ? void 0 : contributor.name) || 'Agent' : undefined;
119
- return getParticipantColor(identity.colorSeed, agentName,
120
- // Keep an explicitly resolved brand consistent with the contributor's icon.
121
- brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId);
115
+ const brandColor = getThirdPartyAgentColor({
116
+ agentNamedId: brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId,
117
+ agentName: brand !== null && brand !== void 0 ? brand : contributor === null || contributor === void 0 ? void 0 : contributor.name
118
+ });
119
+ const agentName = (_ref = brand !== null && brand !== void 0 ? brand : brandColor === null || brandColor === void 0 ? void 0 : brandColor.name) !== null && _ref !== void 0 ? _ref : attribution !== null && attribution !== void 0 && (_attribution$agentId2 = attribution.agentId) !== null && _attribution$agentId2 !== void 0 && _attribution$agentId2.trim() ? (contributor === null || contributor === void 0 ? void 0 : contributor.name) || 'Agent' : undefined;
120
+ return {
121
+ ...getParticipantColor(identity.colorSeed, agentName,
122
+ // Keep an explicitly resolved brand consistent with the contributor's icon.
123
+ brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId),
124
+ scheme: brandColor === null || brandColor === void 0 ? void 0 : brandColor.scheme
125
+ };
122
126
  };
123
127
  export const createAttributionColorMap = (stepAttributions, contributors) => {
124
128
  const colors = new Map();
125
129
  const allocatedColors = new Set();
126
130
 
127
- // Reserve shared brand colours before hashing other actors, regardless of step order. A brand
128
- // slot is pinned deliberately, so it is taken verbatim rather than through `getSlotColor`.
131
+ // Keep brand schemes intact; only unbranded contributors use the hashed ADS palette below.
129
132
  for (const attribution of stepAttributions) {
130
133
  const identity = getAttributionIdentity(attribution);
131
134
  if (!identity) {
@@ -133,11 +136,15 @@ export const createAttributionColorMap = (stepAttributions, contributors) => {
133
136
  }
134
137
  const {
135
138
  index,
136
- isFixed
139
+ isFixed,
140
+ scheme
137
141
  } = getAttributionParticipantColor(attribution, identity, contributors);
142
+ if (scheme) {
143
+ colors.set(identity.key, scheme);
144
+ }
145
+ // Keep the old slot reserved so selecting a brand cannot recolour other contributors.
138
146
  const color = HASHED_PARTICIPANT_COLOR_SCHEMES[index];
139
147
  if (isFixed && color) {
140
- colors.set(identity.key, color);
141
148
  allocatedColors.add(color);
142
149
  }
143
150
  }
@@ -141,8 +141,8 @@ function bgBolder(color) {
141
141
  return (_getBrand$bold = (_getBrand4 = getBrand(color)) === null || _getBrand4 === void 0 ? void 0 : _getBrand4.bold) !== null && _getBrand$bold !== void 0 ? _getBrand$bold : bgBolderMap[color];
142
142
  }
143
143
  function bgSubtlerPressed(color) {
144
- var _getBrand$background3, _getBrand5;
145
- return (_getBrand$background3 = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.background) !== null && _getBrand$background3 !== void 0 ? _getBrand$background3 : bgSubtlerPressedMap[color];
144
+ var _ref, _getBrand$emphasisBac, _getBrand5;
145
+ return (_ref = (_getBrand$emphasisBac = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlerPressedMap[color]) !== null && _ref !== void 0 ? _ref : bgSubtlerPressedMap.gray;
146
146
  }
147
147
  function borderAccent(color) {
148
148
  var _getBrand$border2, _getBrand6;
@@ -153,8 +153,8 @@ function textAccent(color) {
153
153
  return (_getBrand$accentText = (_getBrand7 = getBrand(color)) === null || _getBrand7 === void 0 ? void 0 : _getBrand7.accentText) !== null && _getBrand$accentText !== void 0 ? _getBrand$accentText : textAccentMap[color];
154
154
  }
155
155
  function deletedBackground(color) {
156
- var _getBrand$emphasisBac, _getBrand8;
157
- return (_getBrand$emphasisBac = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlest(color);
156
+ var _getBrand$emphasisBac2, _getBrand8;
157
+ return (_getBrand$emphasisBac2 = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac2 !== void 0 ? _getBrand$emphasisBac2 : bgSubtlest(color);
158
158
  }
159
159
 
160
160
  /** Contributor tags use a bold fill with a contrasting foreground, including branded schemes. */
@@ -236,13 +236,14 @@ export function buildInsertStyleInBlockExtended(colors) {
236
236
 
237
237
  /** Active state of the extended insert style. */
238
238
  export function buildInsertStyleExtendedActive(colors) {
239
+ var _ref2, _brand$activeBorder;
239
240
  const brand = getBrand(colors.insertColor);
240
241
  return convertToInlineCss({
241
242
  background: bgSubtlerPressed(colors.insertActiveColor),
242
243
  ...(brand ? {
243
244
  color: brand.text
244
245
  } : {}),
245
- borderBottom: `2px solid ${borderAccent(colors.insertColor)}`,
246
+ borderBottom: `2px solid ${(_ref2 = (_brand$activeBorder = brand === null || brand === void 0 ? void 0 : brand.activeBorder) !== null && _brand$activeBorder !== void 0 ? _brand$activeBorder : borderAccentMap[colors.insertColor]) !== null && _ref2 !== void 0 ? _ref2 : borderAccentMap.gray}`,
246
247
  padding: `1px 0 2px`
247
248
  });
248
249
  }
@@ -8,37 +8,30 @@ import { getContributorTagIcon } from './contributorTagIcons';
8
8
  const AVATAR_SIZE = AVATAR_SIZES.xxsmall;
9
9
  /** `xxsmall` also carried a `space.025` margin — the same 2px — which is where the ring is painted. */
10
10
  const AVATAR_RING_WIDTH = BORDER_WIDTH;
11
- const AVATAR_BOX_SIZE = AVATAR_SIZE + AVATAR_RING_WIDTH * 2;
12
11
 
13
12
  /** Reused from `@atlaskit/avatar`'s `avatar-content`, so the two shapes cannot drift. */
14
13
  const 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
- const boxStyle = convertToInlineCss({
16
- display: 'inline-flex',
17
- alignItems: 'center',
18
- justifyContent: 'center',
19
- flexShrink: 0,
20
- boxSizing: 'border-box',
21
- width: `${AVATAR_BOX_SIZE}px`,
22
- height: `${AVATAR_BOX_SIZE}px`
23
- });
24
14
 
25
- /** Agents get a drop shadow instead of a ring, so their box skips the ring's padding. */
26
- const agentBoxStyle = convertToInlineCss({
27
- display: 'inline-flex',
28
- alignItems: 'center',
29
- justifyContent: 'center',
30
- flexShrink: 0,
31
- boxSizing: 'border-box',
32
- width: `${AVATAR_SIZE}px`,
33
- height: `${AVATAR_SIZE}px`
34
- });
35
- const shapeStyle = convertToInlineCss({
15
+ /** The avatar plus its ring. */
16
+ const getBoxStyle = (size, ringWidth) => {
17
+ const boxSize = size + ringWidth * 2;
18
+ return convertToInlineCss({
19
+ display: 'inline-flex',
20
+ alignItems: 'center',
21
+ justifyContent: 'center',
22
+ flexShrink: 0,
23
+ boxSizing: 'border-box',
24
+ width: `${boxSize}px`,
25
+ height: `${boxSize}px`
26
+ });
27
+ };
28
+ const getShapeStyle = size => convertToInlineCss({
36
29
  display: 'flex',
37
30
  alignItems: 'center',
38
31
  justifyContent: 'center',
39
32
  boxSizing: 'border-box',
40
- width: `${AVATAR_SIZE}px`,
41
- height: `${AVATAR_SIZE}px`,
33
+ width: `${size}px`,
34
+ height: `${size}px`,
42
35
  aspectRatio: '1/1',
43
36
  overflow: 'hidden'
44
37
  });
@@ -83,11 +76,15 @@ export const contributorAvatarRenderer = ({
83
76
  contributor,
84
77
  doc,
85
78
  ringColor,
79
+ ringWidth = AVATAR_RING_WIDTH,
80
+ size = AVATAR_SIZE,
86
81
  stackIndex
87
82
  }) => {
88
83
  const isAgent = contributor.kind === 'agent';
89
84
  const element = doc.createElement('span');
90
- element.setAttribute('style', isAgent ? `${agentBoxStyle} ${agentShadowStyle}` : boxStyle);
85
+ // Agents get a drop shadow instead of a ring, so their box skips the ring's padding.
86
+ const boxStyle = getBoxStyle(size, isAgent ? 0 : ringWidth);
87
+ element.setAttribute('style', isAgent ? `${boxStyle} ${agentShadowStyle}` : boxStyle);
91
88
  // Decorative: the tag names its contributors in the visually hidden label its screen-reader
92
89
  // announcement comes from.
93
90
  element.setAttribute('aria-hidden', 'true');
@@ -95,7 +92,7 @@ export const contributorAvatarRenderer = ({
95
92
  element.style.setProperty('z-index', String(stackIndex));
96
93
  }
97
94
  const shape = doc.createElement('span');
98
- shape.setAttribute('style', shapeStyle);
95
+ shape.setAttribute('style', getShapeStyle(size));
99
96
  element.appendChild(shape);
100
97
  if (isAgent) {
101
98
  shape.style.setProperty('clip-path', HEXAGON_CLIP_PATH);
@@ -141,7 +138,7 @@ export const contributorAvatarRenderer = ({
141
138
  shape.style.setProperty('background', nextRingColor);
142
139
  return;
143
140
  }
144
- shape.style.setProperty('box-shadow', `0 0 0 ${AVATAR_RING_WIDTH}px ${nextRingColor}`);
141
+ shape.style.setProperty('box-shadow', `0 0 0 ${ringWidth}px ${nextRingColor}`);
145
142
  shape.style.setProperty('background', nextRingColor);
146
143
  };
147
144
  setRingColor(ringColor);
@@ -21,6 +21,13 @@ const getTagAccent = ({
21
21
  return getAccentTokens(accent);
22
22
  };
23
23
 
24
+ /** Person's diameter in a connected pair. */
25
+ const CONNECTED_USER_AVATAR_SIZE = 12;
26
+ /** Px the person overlaps the agent. */
27
+ const CONNECTED_AVATAR_OVERLAP = 3;
28
+ /** Px of ring around the person in a connected pair. */
29
+ const CONNECTED_USER_RING_WIDTH = 1;
30
+
24
31
  /** Bespoke accents for agent kinds that use standard ADS tokens rather than the agent-color registry. */
25
32
  const BESPOKE_AGENT_ACCENTS = {
26
33
  rovo: {
@@ -298,30 +305,35 @@ export class ContributorTagController {
298
305
  const agent = isPrimaryAgent ? model.contributor : model.connectedContributor;
299
306
 
300
307
  // Hand-rolled avatar stack: `@atlaskit/avatar-group` cannot render below 24px and the tag uses
301
- // 16px avatars.
308
+ // 16px avatars. A connected pair's person is smaller and overlaps the agent.
302
309
  const stack = model.connectedContributor ? [...(agent ? [{
303
310
  contributor: agent,
304
- stackIndex: 1
311
+ stackIndex: 0
305
312
  }] : []), ...(user ? [{
306
313
  contributor: user,
307
- stackIndex: 0
314
+ ringWidth: CONNECTED_USER_RING_WIDTH,
315
+ size: CONNECTED_USER_AVATAR_SIZE,
316
+ stackIndex: 1
308
317
  }] : [])] : [{
309
318
  contributor: model.contributor
310
319
  }];
311
320
  stack.forEach(({
312
321
  contributor,
322
+ ringWidth,
323
+ size,
313
324
  stackIndex
314
325
  }, index) => {
315
326
  const avatar = contributorAvatarRenderer({
316
327
  contributor,
317
328
  doc,
318
329
  ringColor: background,
330
+ ringWidth,
331
+ size,
319
332
  stackIndex
320
333
  });
321
334
  if (index < stack.length - 1) {
322
- // Sits the leading avatar of a connected pair flush against the one behind it, with
323
- // no overlap and no extra gap.
324
- avatar.element.style.setProperty('margin-inline-end', '0');
335
+ // The person's ring cuts a gap into the agent.
336
+ avatar.element.style.setProperty('margin-inline-end', `-${CONNECTED_AVATAR_OVERLAP}px`);
325
337
  }
326
338
  container.appendChild(avatar.element);
327
339
  this.avatars.push(avatar);
@@ -22,8 +22,8 @@ import { PARTICIPANT_COLOR_SCHEMES } from './types';
22
22
  var HASHED_PARTICIPANT_COLOR_SCHEMES = [].concat(_toConsumableArray(PARTICIPANT_COLOR_SCHEMES), ['blue', 'red', 'orange', 'yellow', 'green', 'teal', 'purple', 'magenta']);
23
23
 
24
24
  /**
25
- * Red means "deleted" in both public schemes, so it never identifies an actor. Reserving it here
26
- * covers every path into an attribution colour; `createAttributionColorMap` is the only caller, and
25
+ * ADS red means "deleted" in both public schemes, so it is excluded from hashed participant colours.
26
+ * Brand schemes retain their own palettes. `createAttributionColorMap` is the only caller, and
27
27
  * it is gated on `platform_editor_attributed_version_history` plus
28
28
  * `platform_editor_show_diff_color_scheme_refactor`.
29
29
  */
@@ -136,23 +136,25 @@ export var isContributorTagsEnabled = function isContributorTagsEnabled(stepAttr
136
136
  })) && contributors !== undefined && Object.keys(contributors).length > 0;
137
137
  };
138
138
  var getAttributionParticipantColor = function getAttributionParticipantColor(attribution, identity, contributors) {
139
- var _ref2, _getThirdPartyAgentCo, _attribution$agentId2;
139
+ var _ref2, _attribution$agentId2;
140
140
  var contributor = contributors === null || contributors === void 0 ? void 0 : contributors[identity.key];
141
141
  var brand = isDiffAgentBrand(contributor === null || contributor === void 0 ? void 0 : contributor.agentKind) ? contributor === null || contributor === void 0 ? void 0 : contributor.agentKind : undefined;
142
- var agentName = (_ref2 = brand !== null && brand !== void 0 ? brand : (_getThirdPartyAgentCo = getThirdPartyAgentColor({
143
- agentNamedId: attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId,
144
- agentName: contributor === null || contributor === void 0 ? void 0 : contributor.name
145
- })) === null || _getThirdPartyAgentCo === void 0 ? void 0 : _getThirdPartyAgentCo.name) !== null && _ref2 !== void 0 ? _ref2 : attribution !== null && attribution !== void 0 && (_attribution$agentId2 = attribution.agentId) !== null && _attribution$agentId2 !== void 0 && _attribution$agentId2.trim() ? (contributor === null || contributor === void 0 ? void 0 : contributor.name) || 'Agent' : undefined;
146
- return getParticipantColor(identity.colorSeed, agentName,
142
+ var brandColor = getThirdPartyAgentColor({
143
+ agentNamedId: brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId,
144
+ agentName: brand !== null && brand !== void 0 ? brand : contributor === null || contributor === void 0 ? void 0 : contributor.name
145
+ });
146
+ var agentName = (_ref2 = brand !== null && brand !== void 0 ? brand : brandColor === null || brandColor === void 0 ? void 0 : brandColor.name) !== null && _ref2 !== void 0 ? _ref2 : attribution !== null && attribution !== void 0 && (_attribution$agentId2 = attribution.agentId) !== null && _attribution$agentId2 !== void 0 && _attribution$agentId2.trim() ? (contributor === null || contributor === void 0 ? void 0 : contributor.name) || 'Agent' : undefined;
147
+ return _objectSpread(_objectSpread({}, getParticipantColor(identity.colorSeed, agentName,
147
148
  // Keep an explicitly resolved brand consistent with the contributor's icon.
148
- brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId);
149
+ brand ? undefined : attribution === null || attribution === void 0 ? void 0 : attribution.agentNamedId)), {}, {
150
+ scheme: brandColor === null || brandColor === void 0 ? void 0 : brandColor.scheme
151
+ });
149
152
  };
150
153
  export var createAttributionColorMap = function createAttributionColorMap(stepAttributions, contributors) {
151
154
  var colors = new Map();
152
155
  var allocatedColors = new Set();
153
156
 
154
- // Reserve shared brand colours before hashing other actors, regardless of step order. A brand
155
- // slot is pinned deliberately, so it is taken verbatim rather than through `getSlotColor`.
157
+ // Keep brand schemes intact; only unbranded contributors use the hashed ADS palette below.
156
158
  var _iterator2 = _createForOfIteratorHelper(stepAttributions),
157
159
  _step2;
158
160
  try {
@@ -164,10 +166,14 @@ export var createAttributionColorMap = function createAttributionColorMap(stepAt
164
166
  }
165
167
  var _getAttributionPartic = getAttributionParticipantColor(attribution, identity, contributors),
166
168
  index = _getAttributionPartic.index,
167
- isFixed = _getAttributionPartic.isFixed;
169
+ isFixed = _getAttributionPartic.isFixed,
170
+ scheme = _getAttributionPartic.scheme;
171
+ if (scheme) {
172
+ colors.set(identity.key, scheme);
173
+ }
174
+ // Keep the old slot reserved so selecting a brand cannot recolour other contributors.
168
175
  var color = HASHED_PARTICIPANT_COLOR_SCHEMES[index];
169
176
  if (isFixed && color) {
170
- colors.set(identity.key, color);
171
177
  allocatedColors.add(color);
172
178
  }
173
179
  }
@@ -146,8 +146,8 @@ function bgBolder(color) {
146
146
  return (_getBrand$bold = (_getBrand4 = getBrand(color)) === null || _getBrand4 === void 0 ? void 0 : _getBrand4.bold) !== null && _getBrand$bold !== void 0 ? _getBrand$bold : bgBolderMap[color];
147
147
  }
148
148
  function bgSubtlerPressed(color) {
149
- var _getBrand$background3, _getBrand5;
150
- return (_getBrand$background3 = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.background) !== null && _getBrand$background3 !== void 0 ? _getBrand$background3 : bgSubtlerPressedMap[color];
149
+ var _ref, _getBrand$emphasisBac, _getBrand5;
150
+ return (_ref = (_getBrand$emphasisBac = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlerPressedMap[color]) !== null && _ref !== void 0 ? _ref : bgSubtlerPressedMap.gray;
151
151
  }
152
152
  function borderAccent(color) {
153
153
  var _getBrand$border2, _getBrand6;
@@ -158,8 +158,8 @@ function textAccent(color) {
158
158
  return (_getBrand$accentText = (_getBrand7 = getBrand(color)) === null || _getBrand7 === void 0 ? void 0 : _getBrand7.accentText) !== null && _getBrand$accentText !== void 0 ? _getBrand$accentText : textAccentMap[color];
159
159
  }
160
160
  function deletedBackground(color) {
161
- var _getBrand$emphasisBac, _getBrand8;
162
- return (_getBrand$emphasisBac = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlest(color);
161
+ var _getBrand$emphasisBac2, _getBrand8;
162
+ return (_getBrand$emphasisBac2 = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac2 !== void 0 ? _getBrand$emphasisBac2 : bgSubtlest(color);
163
163
  }
164
164
 
165
165
  /** Contributor tags use a bold fill with a contrasting foreground, including branded schemes. */
@@ -241,13 +241,14 @@ export function buildInsertStyleInBlockExtended(colors) {
241
241
 
242
242
  /** Active state of the extended insert style. */
243
243
  export function buildInsertStyleExtendedActive(colors) {
244
+ var _ref2, _brand$activeBorder;
244
245
  var brand = getBrand(colors.insertColor);
245
246
  return convertToInlineCss(_objectSpread(_objectSpread({
246
247
  background: bgSubtlerPressed(colors.insertActiveColor)
247
248
  }, brand ? {
248
249
  color: brand.text
249
250
  } : {}), {}, {
250
- borderBottom: "2px solid ".concat(borderAccent(colors.insertColor)),
251
+ borderBottom: "2px solid ".concat((_ref2 = (_brand$activeBorder = brand === null || brand === void 0 ? void 0 : brand.activeBorder) !== null && _brand$activeBorder !== void 0 ? _brand$activeBorder : borderAccentMap[colors.insertColor]) !== null && _ref2 !== void 0 ? _ref2 : borderAccentMap.gray),
251
252
  padding: "1px 0 2px"
252
253
  }));
253
254
  }
@@ -1042,9 +1043,9 @@ export function buildDeletedQuoteNodeWithLozengeStyle(colors, isActive) {
1042
1043
  * codeBlock). Every scheme shares the active state; `deletedNodeEmphasis` changes only the
1043
1044
  * resting one — 'stateful' a 4px subtlest ring, 'static' a 1px accent ring.
1044
1045
  */
1045
- export function buildDeletedWrappedBlockOutline(colors, _ref) {
1046
- var isActive = _ref.isActive,
1047
- isRounded = _ref.isRounded;
1046
+ export function buildDeletedWrappedBlockOutline(colors, _ref3) {
1047
+ var isActive = _ref3.isActive,
1048
+ isRounded = _ref3.isRounded;
1048
1049
  if (isActive) {
1049
1050
  return isRounded ? buildDeletedBlockOutlineRoundedActive(colors) : buildDeletedBlockOutlineActive(colors);
1050
1051
  }
@@ -8,40 +8,35 @@ import { getContributorTagIcon } from './contributorTagIcons';
8
8
  var AVATAR_SIZE = AVATAR_SIZES.xxsmall;
9
9
  /** `xxsmall` also carried a `space.025` margin — the same 2px — which is where the ring is painted. */
10
10
  var AVATAR_RING_WIDTH = BORDER_WIDTH;
11
- var AVATAR_BOX_SIZE = AVATAR_SIZE + AVATAR_RING_WIDTH * 2;
12
11
 
13
12
  /** Reused from `@atlaskit/avatar`'s `avatar-content`, so the two shapes cannot drift. */
14
13
  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
14
 
25
- /** Agents get a drop shadow instead of a ring, so their box skips the ring's padding. */
26
- var agentBoxStyle = convertToInlineCss({
27
- display: 'inline-flex',
28
- alignItems: 'center',
29
- justifyContent: 'center',
30
- flexShrink: 0,
31
- boxSizing: 'border-box',
32
- width: "".concat(AVATAR_SIZE, "px"),
33
- height: "".concat(AVATAR_SIZE, "px")
34
- });
35
- var shapeStyle = convertToInlineCss({
36
- display: 'flex',
37
- alignItems: 'center',
38
- justifyContent: 'center',
39
- boxSizing: 'border-box',
40
- width: "".concat(AVATAR_SIZE, "px"),
41
- height: "".concat(AVATAR_SIZE, "px"),
42
- aspectRatio: '1/1',
43
- overflow: 'hidden'
44
- });
15
+ /** The avatar plus its ring. */
16
+ var getBoxStyle = function getBoxStyle(size, ringWidth) {
17
+ var boxSize = size + ringWidth * 2;
18
+ return convertToInlineCss({
19
+ display: 'inline-flex',
20
+ alignItems: 'center',
21
+ justifyContent: 'center',
22
+ flexShrink: 0,
23
+ boxSizing: 'border-box',
24
+ width: "".concat(boxSize, "px"),
25
+ height: "".concat(boxSize, "px")
26
+ });
27
+ };
28
+ var getShapeStyle = function getShapeStyle(size) {
29
+ return convertToInlineCss({
30
+ display: 'flex',
31
+ alignItems: 'center',
32
+ justifyContent: 'center',
33
+ boxSizing: 'border-box',
34
+ width: "".concat(size, "px"),
35
+ height: "".concat(size, "px"),
36
+ aspectRatio: '1/1',
37
+ overflow: 'hidden'
38
+ });
39
+ };
45
40
 
46
41
  /**
47
42
  * The shadow's colour per theme. In the dark theme `elevation.shadow.overflow.perimeter` is
@@ -83,10 +78,16 @@ export var contributorAvatarRenderer = function contributorAvatarRenderer(_ref)
83
78
  var contributor = _ref.contributor,
84
79
  doc = _ref.doc,
85
80
  ringColor = _ref.ringColor,
81
+ _ref$ringWidth = _ref.ringWidth,
82
+ ringWidth = _ref$ringWidth === void 0 ? AVATAR_RING_WIDTH : _ref$ringWidth,
83
+ _ref$size = _ref.size,
84
+ size = _ref$size === void 0 ? AVATAR_SIZE : _ref$size,
86
85
  stackIndex = _ref.stackIndex;
87
86
  var isAgent = contributor.kind === 'agent';
88
87
  var element = doc.createElement('span');
89
- element.setAttribute('style', isAgent ? "".concat(agentBoxStyle, " ").concat(agentShadowStyle) : boxStyle);
88
+ // Agents get a drop shadow instead of a ring, so their box skips the ring's padding.
89
+ var boxStyle = getBoxStyle(size, isAgent ? 0 : ringWidth);
90
+ element.setAttribute('style', isAgent ? "".concat(boxStyle, " ").concat(agentShadowStyle) : boxStyle);
90
91
  // Decorative: the tag names its contributors in the visually hidden label its screen-reader
91
92
  // announcement comes from.
92
93
  element.setAttribute('aria-hidden', 'true');
@@ -94,7 +95,7 @@ export var contributorAvatarRenderer = function contributorAvatarRenderer(_ref)
94
95
  element.style.setProperty('z-index', String(stackIndex));
95
96
  }
96
97
  var shape = doc.createElement('span');
97
- shape.setAttribute('style', shapeStyle);
98
+ shape.setAttribute('style', getShapeStyle(size));
98
99
  element.appendChild(shape);
99
100
  if (isAgent) {
100
101
  shape.style.setProperty('clip-path', HEXAGON_CLIP_PATH);
@@ -140,7 +141,7 @@ export var contributorAvatarRenderer = function contributorAvatarRenderer(_ref)
140
141
  shape.style.setProperty('background', nextRingColor);
141
142
  return;
142
143
  }
143
- shape.style.setProperty('box-shadow', "0 0 0 ".concat(AVATAR_RING_WIDTH, "px ").concat(nextRingColor));
144
+ shape.style.setProperty('box-shadow', "0 0 0 ".concat(ringWidth, "px ").concat(nextRingColor));
144
145
  shape.style.setProperty('background', nextRingColor);
145
146
  };
146
147
  setRingColor(ringColor);
@@ -25,6 +25,13 @@ var getTagAccent = function getTagAccent(_ref) {
25
25
  return getAccentTokens(accent);
26
26
  };
27
27
 
28
+ /** Person's diameter in a connected pair. */
29
+ var CONNECTED_USER_AVATAR_SIZE = 12;
30
+ /** Px the person overlaps the agent. */
31
+ var CONNECTED_AVATAR_OVERLAP = 3;
32
+ /** Px of ring around the person in a connected pair. */
33
+ var CONNECTED_USER_RING_WIDTH = 1;
34
+
28
35
  /** Bespoke accents for agent kinds that use standard ADS tokens rather than the agent-color registry. */
29
36
  var BESPOKE_AGENT_ACCENTS = {
30
37
  rovo: {
@@ -335,29 +342,34 @@ export var ContributorTagController = /*#__PURE__*/function () {
335
342
  var agent = isPrimaryAgent ? model.contributor : model.connectedContributor;
336
343
 
337
344
  // Hand-rolled avatar stack: `@atlaskit/avatar-group` cannot render below 24px and the tag uses
338
- // 16px avatars.
345
+ // 16px avatars. A connected pair's person is smaller and overlaps the agent.
339
346
  var stack = model.connectedContributor ? [].concat(_toConsumableArray(agent ? [{
340
347
  contributor: agent,
341
- stackIndex: 1
348
+ stackIndex: 0
342
349
  }] : []), _toConsumableArray(user ? [{
343
350
  contributor: user,
344
- stackIndex: 0
351
+ ringWidth: CONNECTED_USER_RING_WIDTH,
352
+ size: CONNECTED_USER_AVATAR_SIZE,
353
+ stackIndex: 1
345
354
  }] : [])) : [{
346
355
  contributor: model.contributor
347
356
  }];
348
357
  stack.forEach(function (_ref6, index) {
349
358
  var contributor = _ref6.contributor,
359
+ ringWidth = _ref6.ringWidth,
360
+ size = _ref6.size,
350
361
  stackIndex = _ref6.stackIndex;
351
362
  var avatar = contributorAvatarRenderer({
352
363
  contributor: contributor,
353
364
  doc: doc,
354
365
  ringColor: background,
366
+ ringWidth: ringWidth,
367
+ size: size,
355
368
  stackIndex: stackIndex
356
369
  });
357
370
  if (index < stack.length - 1) {
358
- // Sits the leading avatar of a connected pair flush against the one behind it, with
359
- // no overlap and no extra gap.
360
- avatar.element.style.setProperty('margin-inline-end', '0');
371
+ // The person's ring cuts a gap into the agent.
372
+ avatar.element.style.setProperty('margin-inline-end', "-".concat(CONNECTED_AVATAR_OVERLAP, "px"));
361
373
  }
362
374
  container.appendChild(avatar.element);
363
375
  _this5.avatars.push(avatar);
@@ -1,6 +1,6 @@
1
1
  import type { Change } from 'prosemirror-changeset';
2
2
  import { type DiffContributors, type DiffStepAttribution, type TagContributor } from '../../../showDiffPluginType';
3
- import { type AdsAccentColor, type ColorScheme } from './types';
3
+ import { type AccentColor, type ColorScheme } from './types';
4
4
  export type DiffAttributionSpanData = DiffStepAttribution & {
5
5
  stepIndex: number;
6
6
  };
@@ -24,10 +24,10 @@ export declare const isAttributionColoringEnabled: (stepAttributions: Array<Diff
24
24
  * a tag only has to name one.
25
25
  */
26
26
  export declare const isContributorTagsEnabled: (stepAttributions: Array<DiffStepAttribution | undefined> | undefined, contributors: ResolvedDiffContributors | undefined) => boolean;
27
- export declare const createAttributionColorMap: (stepAttributions: Array<DiffStepAttribution | undefined>, contributors?: ResolvedDiffContributors) => Map<string, AdsAccentColor>;
27
+ export declare const createAttributionColorMap: (stepAttributions: Array<DiffStepAttribution | undefined>, contributors?: ResolvedDiffContributors) => Map<string, AccentColor>;
28
28
  /**
29
29
  * Preserve overlap attribution outside Confluence version history. Within version history, a
30
30
  * recovery step's keyless spans must not inherit an overlapping NCS step's actor.
31
31
  */
32
32
  export declare const getAttributionKeyForChange: (change: Change, attributedChanges: Change[]) => string | undefined;
33
- export declare const getColorSchemeForChange: (change: Change, attributedChanges: Change[], attributionColors: Map<string, AdsAccentColor>, fallback: ColorScheme | undefined) => ColorScheme | undefined;
33
+ export declare const getColorSchemeForChange: (change: Change, attributedChanges: Change[], attributionColors: Map<string, AccentColor>, fallback: ColorScheme | undefined) => ColorScheme | undefined;
@@ -13,10 +13,14 @@ export type ContributorAvatar = {
13
13
  * `box-shadow` on the circle and a second clipped hexagon behind the agent, since `box-shadow` is
14
14
  * cut away by `clip-path`.
15
15
  */
16
- export declare const contributorAvatarRenderer: ({ contributor, doc, ringColor, stackIndex, }: {
16
+ export declare const contributorAvatarRenderer: ({ contributor, doc, ringColor, ringWidth, size, stackIndex, }: {
17
17
  contributor: TagContributor;
18
18
  doc: Document;
19
19
  ringColor: string;
20
- /** Paints the leading avatar of a connected pair over the one it overlaps. */
20
+ /** Ring width in px around a person. */
21
+ ringWidth?: number;
22
+ /** Diameter in px. */
23
+ size?: number;
24
+ /** Paints above lower indexes: the person (1) over the agent (0) in a connected pair. */
21
25
  stackIndex?: number;
22
26
  }) => ContributorAvatar;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-show-diff",
3
- "version": "30.0.10",
3
+ "version": "30.0.12",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -26,7 +26,7 @@
26
26
  "atlaskit:src": "src/index.ts",
27
27
  "dependencies": {
28
28
  "@atlaskit/adf-schema": "^57.7.0",
29
- "@atlaskit/agent-color": "^1.0.0",
29
+ "@atlaskit/agent-color": "^1.1.0",
30
30
  "@atlaskit/avatar": "^30.1.0",
31
31
  "@atlaskit/custom-steps": "^1.1.0",
32
32
  "@atlaskit/editor-plugin-accessibility-utils": "^30.0.0",
@@ -38,9 +38,9 @@
38
38
  "@atlaskit/editor-tables": "^3.2.0",
39
39
  "@atlaskit/platform-feature-experiments": "^0.3.0",
40
40
  "@atlaskit/platform-feature-flags": "^2.2.0",
41
- "@atlaskit/primitives": "^22.6.0",
42
- "@atlaskit/tmp-editor-statsig": "^259.0.0",
43
- "@atlaskit/tokens": "^20.9.0",
41
+ "@atlaskit/primitives": "^22.7.0",
42
+ "@atlaskit/tmp-editor-statsig": "^260.0.0",
43
+ "@atlaskit/tokens": "^20.10.0",
44
44
  "@babel/runtime": "^7.0.0",
45
45
  "@compiled/react": "^1.0.2",
46
46
  "bind-event-listener": "^3.0.0",
@@ -53,8 +53,8 @@
53
53
  "@atlaskit/button": "^25.7.0",
54
54
  "@atlaskit/css": "^1.1.0",
55
55
  "@atlaskit/dropdown-menu": "^21.1.0",
56
- "@atlaskit/editor-common": "^134.9.0",
57
- "@atlaskit/editor-core": "^242.0.0",
56
+ "@atlaskit/editor-common": "^134.10.0",
57
+ "@atlaskit/editor-core": "^242.2.0",
58
58
  "@atlaskit/editor-json-transformer": "^10.0.0",
59
59
  "@atlaskit/editor-plugins": "^17.0.0",
60
60
  "@atlaskit/form": "^18.3.0",
@@ -65,14 +65,14 @@
65
65
  "@atlassian/confluence-presets": "workspace:^",
66
66
  "@atlassian/content-reconciliation": "^0.1.3506",
67
67
  "@atlassian/editor-ai-injected-editors": "^46.0.0",
68
- "@atlassian/editor-plugin-ai": "^84.7.0",
68
+ "@atlassian/editor-plugin-ai": "^84.8.0",
69
69
  "@atlassian/structured-docs-types": "workspace:^",
70
70
  "react": "^19.2.0",
71
71
  "react-dom": "^19.2.0",
72
72
  "react-intl": "^7.0.0"
73
73
  },
74
74
  "peerDependencies": {
75
- "@atlaskit/editor-common": "^134.9.0",
75
+ "@atlaskit/editor-common": "^134.10.0",
76
76
  "react": "^18.2.0 || ^19.2.0",
77
77
  "react-dom": "^18.2.0 || ^19.2.0",
78
78
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"