@atlaskit/editor-plugin-show-diff 19.0.3 → 19.0.4

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 (94) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +57 -93
  3. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +1 -1
  4. package/dist/cjs/pm-plugins/decorations/colorSchemes/standard.js +1 -26
  5. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +12 -24
  6. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.styles.legacy.js +25 -57
  7. package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +22 -60
  8. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +8 -16
  9. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.styles.legacy.js +7 -22
  10. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +34 -52
  11. package/dist/cjs/pm-plugins/decorations/decorationKeys.js +6 -14
  12. package/dist/cjs/pm-plugins/decorations/utils/createDeletedLineBreakWidget.js +3 -8
  13. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +132 -205
  14. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +13 -20
  15. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +6 -10
  16. package/dist/cjs/pm-plugins/getDefaultDiffType.js +10 -0
  17. package/dist/cjs/pm-plugins/getScrollableDecorations.js +5 -15
  18. package/dist/cjs/pm-plugins/main.js +45 -53
  19. package/dist/cjs/pm-plugins/resolveDiffContributors.js +18 -4
  20. package/dist/cjs/showDiffPlugin.js +14 -24
  21. package/dist/cjs/showDiffPluginType.js +1 -1
  22. package/dist/cjs/ui/ContributorTag/contributorAvatarRenderer.js +19 -9
  23. package/dist/cjs/ui/ContributorTag/contributorTagController.js +28 -3
  24. package/dist/cjs/ui/ContributorTag/contributorTagIcons.js +2 -2
  25. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +67 -105
  26. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +1 -1
  27. package/dist/es2019/pm-plugins/decorations/colorSchemes/standard.js +0 -26
  28. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +11 -23
  29. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.styles.legacy.js +25 -57
  30. package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +22 -60
  31. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +8 -18
  32. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.styles.legacy.js +8 -23
  33. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +34 -54
  34. package/dist/es2019/pm-plugins/decorations/decorationKeys.js +6 -16
  35. package/dist/es2019/pm-plugins/decorations/utils/createDeletedLineBreakWidget.js +2 -7
  36. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +53 -125
  37. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +11 -12
  38. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +6 -7
  39. package/dist/es2019/pm-plugins/getDefaultDiffType.js +2 -0
  40. package/dist/es2019/pm-plugins/getScrollableDecorations.js +6 -19
  41. package/dist/es2019/pm-plugins/main.js +49 -65
  42. package/dist/es2019/pm-plugins/resolveDiffContributors.js +18 -3
  43. package/dist/es2019/showDiffPlugin.js +12 -24
  44. package/dist/es2019/showDiffPluginType.js +1 -1
  45. package/dist/es2019/ui/ContributorTag/contributorAvatarRenderer.js +19 -9
  46. package/dist/es2019/ui/ContributorTag/contributorTagController.js +30 -2
  47. package/dist/es2019/ui/ContributorTag/contributorTagIcons.js +2 -2
  48. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +56 -92
  49. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +1 -1
  50. package/dist/esm/pm-plugins/decorations/colorSchemes/standard.js +0 -26
  51. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +12 -24
  52. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.styles.legacy.js +25 -57
  53. package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +22 -60
  54. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +8 -16
  55. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.styles.legacy.js +8 -23
  56. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +34 -52
  57. package/dist/esm/pm-plugins/decorations/decorationKeys.js +6 -14
  58. package/dist/esm/pm-plugins/decorations/utils/createDeletedLineBreakWidget.js +3 -8
  59. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +132 -205
  60. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +13 -20
  61. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +6 -10
  62. package/dist/esm/pm-plugins/getDefaultDiffType.js +4 -0
  63. package/dist/esm/pm-plugins/getScrollableDecorations.js +6 -16
  64. package/dist/esm/pm-plugins/main.js +44 -52
  65. package/dist/esm/pm-plugins/resolveDiffContributors.js +18 -4
  66. package/dist/esm/showDiffPlugin.js +14 -24
  67. package/dist/esm/showDiffPluginType.js +1 -1
  68. package/dist/esm/ui/ContributorTag/contributorAvatarRenderer.js +19 -9
  69. package/dist/esm/ui/ContributorTag/contributorTagController.js +28 -3
  70. package/dist/esm/ui/ContributorTag/contributorTagIcons.js +2 -2
  71. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +1 -1
  72. package/dist/types/pm-plugins/decorations/colorSchemes/standard.d.ts +0 -3
  73. package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +1 -1
  74. package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.d.ts +1 -3
  75. package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.styles.legacy.d.ts +2 -3
  76. package/dist/types/pm-plugins/decorations/createChangedRowDecorationWidgets.d.ts +1 -3
  77. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -3
  78. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.styles.legacy.d.ts +2 -3
  79. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +2 -3
  80. package/dist/types/pm-plugins/decorations/decorationKeys.d.ts +5 -8
  81. package/dist/types/pm-plugins/decorations/utils/createDeletedLineBreakWidget.d.ts +3 -5
  82. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +4 -6
  83. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.d.ts +3 -4
  84. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.d.ts +4 -4
  85. package/dist/types/pm-plugins/getDefaultDiffType.d.ts +2 -0
  86. package/dist/types/pm-plugins/getScrollableDecorations.d.ts +1 -2
  87. package/dist/types/pm-plugins/main.d.ts +0 -1
  88. package/dist/types/showDiffPluginType.d.ts +1 -3
  89. package/docs/smart-diff-design.md +13 -29
  90. package/package.json +5 -5
  91. package/dist/cjs/pm-plugins/isExtendedEnabled.js +0 -23
  92. package/dist/es2019/pm-plugins/isExtendedEnabled.js +0 -13
  93. package/dist/esm/pm-plugins/isExtendedEnabled.js +0 -17
  94. package/dist/types/pm-plugins/isExtendedEnabled.d.ts +0 -12
@@ -8,8 +8,8 @@ import { getActiveDiffAnnouncement } from '../ui/DiffNavigation/announceActiveDi
8
8
  import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
9
9
  import { isDiffDecoration, isDiffDecorationSpec } from './decorations/decorationKeys';
10
10
  import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
11
+ import { getDefaultDiffType } from './getDefaultDiffType';
11
12
  import { getScrollableDecorations } from './getScrollableDecorations';
12
- import { getDefaultDiffType, isExtendedEnabled } from './isExtendedEnabled';
13
13
  import { NodeViewSerializer } from './NodeViewSerializer';
14
14
  import { rebindReveal } from './revealAnimation';
15
15
  import { scrollToDecoration } from './scrollToDiff';
@@ -61,21 +61,18 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
61
61
  state: {
62
62
  init(_, _state) {
63
63
  // We do initial setup after we setup the editor view
64
- const defaultDiffType = getDefaultDiffType();
65
64
  return {
66
65
  steps: [],
67
66
  stepAttributions: [],
68
67
  originalDoc: undefined,
69
68
  decorations: DecorationSet.empty,
70
69
  isDisplayingChanges: false,
71
- ...(isExtendedEnabled(defaultDiffType) ? {
72
- isInverted: false,
73
- diffType: defaultDiffType,
74
- hideDeletedDiffs: false,
75
- hideAddedDiffsUnderline: false,
76
- showIndicators: false,
77
- diffDescriptors: []
78
- } : {})
70
+ isInverted: false,
71
+ diffType: getDefaultDiffType(),
72
+ hideDeletedDiffs: false,
73
+ hideAddedDiffsUnderline: false,
74
+ showIndicators: false,
75
+ diffDescriptors: []
79
76
  };
80
77
  },
81
78
  apply: (tr, currentPluginState, oldState, newState) => {
@@ -83,7 +80,7 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
83
80
  let newPluginState = currentPluginState;
84
81
  if (meta) {
85
82
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'REVEAL_COMPLETE') {
86
- var _newPluginState$color, _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8, _newPluginState9, _newPluginState0, _newPluginState1, _newPluginState10;
83
+ var _newPluginState$color, _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8, _newPluginState9, _newPluginState0;
87
84
  // REVEAL_COMPLETE repaints with the reveal dropped, so the decorations render their
88
85
  // ordinary resting style. Without it the reveal stays in state indefinitely and the
89
86
  // next unrelated repaint re-emits the hidden, zero-width highlight with no animation
@@ -115,26 +112,22 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
115
112
  activeIndexPos: newPluginState.activeIndexPos,
116
113
  api,
117
114
  tagMountContext,
118
- ...(isExtendedEnabled((_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.diffType) ? {
119
- isInverted: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.isInverted,
120
- diffType: (_newPluginState4 = newPluginState) === null || _newPluginState4 === void 0 ? void 0 : _newPluginState4.diffType,
121
- hideDeletedDiffs: (_newPluginState5 = newPluginState) === null || _newPluginState5 === void 0 ? void 0 : _newPluginState5.hideDeletedDiffs,
122
- hideAddedDiffsUnderline: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.hideAddedDiffsUnderline,
123
- showIndicators: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.showIndicators,
124
- smartThresholds: (_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.smartThresholds,
125
- deletedDiffPlacement: (_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.deletedDiffPlacement,
126
- inlineDeletedDiffPlacement: (_newPluginState0 = newPluginState) === null || _newPluginState0 === void 0 ? void 0 : _newPluginState0.inlineDeletedDiffPlacement,
127
- // SHOW_DIFF only. The scroll-to-next recalculation further down deliberately
128
- // omits this so stepping through changes cannot replay the choreography.
129
- reveal: (_newPluginState1 = newPluginState) === null || _newPluginState1 === void 0 ? void 0 : _newPluginState1.reveal
130
- } : {})
115
+ isInverted: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.isInverted,
116
+ diffType: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.diffType,
117
+ hideDeletedDiffs: (_newPluginState4 = newPluginState) === null || _newPluginState4 === void 0 ? void 0 : _newPluginState4.hideDeletedDiffs,
118
+ hideAddedDiffsUnderline: (_newPluginState5 = newPluginState) === null || _newPluginState5 === void 0 ? void 0 : _newPluginState5.hideAddedDiffsUnderline,
119
+ showIndicators: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.showIndicators,
120
+ smartThresholds: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.smartThresholds,
121
+ deletedDiffPlacement: (_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.deletedDiffPlacement,
122
+ inlineDeletedDiffPlacement: (_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.inlineDeletedDiffPlacement,
123
+ // SHOW_DIFF only. The scroll-to-next recalculation further down deliberately
124
+ // omits this so stepping through changes cannot replay the choreography.
125
+ reveal: (_newPluginState0 = newPluginState) === null || _newPluginState0 === void 0 ? void 0 : _newPluginState0.reveal
131
126
  });
132
127
  // Update the decorations and their ids
133
128
  newPluginState.decorations = decorations;
134
129
  newPluginState.contributorTags = contributorTags;
135
- if (isExtendedEnabled((_newPluginState10 = newPluginState) === null || _newPluginState10 === void 0 ? void 0 : _newPluginState10.diffType)) {
136
- newPluginState.diffDescriptors = diffDescriptors;
137
- }
130
+ newPluginState.diffDescriptors = diffDescriptors;
138
131
  } else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'HIDE_DIFF') {
139
132
  newPluginState = {
140
133
  ...currentPluginState,
@@ -150,20 +143,17 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
150
143
  * Reset isInverted & diffType state when hiding diffs
151
144
  * Otherwise this should persist for the diff-showing session
152
145
  */
153
- ...(isExtendedEnabled(currentPluginState.diffType) ? {
154
- isInverted: false,
155
- diffType: getDefaultDiffType(),
156
- hideDeletedDiffs: false,
157
- hideAddedDiffsUnderline: false,
158
- diffDescriptors: []
159
- } : {})
146
+ isInverted: false,
147
+ diffType: getDefaultDiffType(),
148
+ hideDeletedDiffs: false,
149
+ hideAddedDiffsUnderline: false,
150
+ diffDescriptors: []
160
151
  };
161
152
  } else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') {
162
- var _newPluginState11;
163
153
  // Update the active index in plugin state and recalculate decorations
164
- const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (_newPluginState11 = newPluginState) === null || _newPluginState11 === void 0 ? void 0 : _newPluginState11.diffType);
154
+ const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc);
165
155
  if (decorations.length > 0) {
166
- var _currentPluginState$a, _newPluginState$color2, _newPluginState12;
156
+ var _currentPluginState$a, _newPluginState$color2, _newPluginState1;
167
157
  // Initialize to -1 if undefined so that the first "next" scroll takes us to index 0 (first change).
168
158
  // This allows the UI to start with no selection and only highlight on first user interaction.
169
159
  let nextIndex = (_currentPluginState$a = currentPluginState.activeIndex) !== null && _currentPluginState$a !== void 0 ? _currentPluginState$a : -1;
@@ -196,27 +186,23 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
196
186
  state: newState,
197
187
  pluginState: newPluginState,
198
188
  nodeViewSerializer,
199
- colorScheme: (_newPluginState$color2 = (_newPluginState12 = newPluginState) === null || _newPluginState12 === void 0 ? void 0 : _newPluginState12.colorScheme) !== null && _newPluginState$color2 !== void 0 ? _newPluginState$color2 : config === null || config === void 0 ? void 0 : config.colorScheme,
189
+ colorScheme: (_newPluginState$color2 = (_newPluginState1 = newPluginState) === null || _newPluginState1 === void 0 ? void 0 : _newPluginState1.colorScheme) !== null && _newPluginState$color2 !== void 0 ? _newPluginState$color2 : config === null || config === void 0 ? void 0 : config.colorScheme,
200
190
  intl: getIntl(),
201
191
  activeIndexPos: newPluginState.activeIndexPos,
202
192
  api,
203
193
  tagMountContext,
204
- ...(isExtendedEnabled(newPluginState.diffType) ? {
205
- isInverted: newPluginState.isInverted,
206
- diffType: newPluginState.diffType,
207
- hideDeletedDiffs: newPluginState.hideDeletedDiffs,
208
- hideAddedDiffsUnderline: newPluginState.hideAddedDiffsUnderline,
209
- showIndicators: newPluginState.showIndicators,
210
- smartThresholds: newPluginState.smartThresholds,
211
- deletedDiffPlacement: newPluginState.deletedDiffPlacement,
212
- inlineDeletedDiffPlacement: newPluginState.inlineDeletedDiffPlacement
213
- } : {})
194
+ isInverted: newPluginState.isInverted,
195
+ diffType: newPluginState.diffType,
196
+ hideDeletedDiffs: newPluginState.hideDeletedDiffs,
197
+ hideAddedDiffsUnderline: newPluginState.hideAddedDiffsUnderline,
198
+ showIndicators: newPluginState.showIndicators,
199
+ smartThresholds: newPluginState.smartThresholds,
200
+ deletedDiffPlacement: newPluginState.deletedDiffPlacement,
201
+ inlineDeletedDiffPlacement: newPluginState.inlineDeletedDiffPlacement
214
202
  });
215
203
  newPluginState.decorations = updatedDecorations;
216
204
  newPluginState.contributorTags = updatedContributorTags;
217
- if (isExtendedEnabled(newPluginState.diffType)) {
218
- newPluginState.diffDescriptors = updatedDiffDescriptors;
219
- }
205
+ newPluginState.diffDescriptors = updatedDiffDescriptors;
220
206
  }
221
207
  } else {
222
208
  newPluginState = {
@@ -263,10 +249,10 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
263
249
  // Scroll to the first decoration when scrollIntoView was requested.
264
250
  // Use the same filtered/position-sorted list as the active-index path
265
251
  // so "first" reliably means the topmost scrollable diff in the document.
266
- if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView && isExtendedEnabled(pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffType)) {
252
+ if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView) {
267
253
  var _cancelPendingScrollT;
268
254
  (_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 ? void 0 : _cancelPendingScrollT();
269
- cancelPendingScrollToDecoration = scrollToDecoration(view, getScrollableDecorations(pluginState.decorations, view.state.doc, pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffType), undefined, api);
255
+ cancelPendingScrollToDecoration = scrollToDecoration(view, getScrollableDecorations(pluginState.decorations, view.state.doc), undefined, api);
270
256
 
271
257
  // Reset the flag so we don't scroll again on subsequent updates
272
258
  view.dispatch(view.state.tr.setMeta(showDiffPluginKey, {
@@ -280,7 +266,7 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
280
266
  if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && activeIndexChanged) {
281
267
  var _cancelPendingScrollT2;
282
268
  (_cancelPendingScrollT2 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT2 === void 0 ? void 0 : _cancelPendingScrollT2();
283
- const scrollableDecorations = getScrollableDecorations(pluginState.decorations, view.state.doc, pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffType);
269
+ const scrollableDecorations = getScrollableDecorations(pluginState.decorations, view.state.doc);
284
270
  const activeDecoration = scrollableDecorations[pluginState.activeIndex];
285
271
  if (activeDecoration) {
286
272
  // EDITOR-7926: use editor-common's command instead of the expand plugin API to
@@ -293,17 +279,15 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
293
279
  // screen-reader user gets silence. Announced through the live region rather than by
294
280
  // focusing the change, since the "next change" control has to stay focused to be
295
281
  // pressed again. After the scroll above, so the announcement never precedes it.
296
- if (isExtendedEnabled(pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffType)) {
297
- const announcement = getActiveDiffAnnouncement({
298
- activeIndex: pluginState.activeIndex,
299
- contributorTags: pluginState.contributorTags,
300
- decorations: scrollableDecorations,
301
- intl: getIntl()
302
- });
303
- if (announcement) {
304
- var _api$accessibilityUti;
305
- api === null || api === void 0 ? void 0 : (_api$accessibilityUti = api.accessibilityUtils) === null || _api$accessibilityUti === void 0 ? void 0 : _api$accessibilityUti.actions.ariaNotify(announcement);
306
- }
282
+ const announcement = getActiveDiffAnnouncement({
283
+ activeIndex: pluginState.activeIndex,
284
+ contributorTags: pluginState.contributorTags,
285
+ decorations: scrollableDecorations,
286
+ intl: getIntl()
287
+ });
288
+ if (announcement) {
289
+ var _api$accessibilityUti;
290
+ api === null || api === void 0 ? void 0 : (_api$accessibilityUti = api.accessibilityUtils) === null || _api$accessibilityUti === void 0 ? void 0 : _api$accessibilityUti.actions.ariaNotify(announcement);
307
291
  }
308
292
  }
309
293
  },
@@ -10,9 +10,19 @@ const ROVO_AGENT_TYPES = new Set(['convo-ai', 'rovo_chat']);
10
10
  const SHOW_DIFF_AGENT_BRANDS = {
11
11
  'agent-brand-claude': 'claude',
12
12
  'agent-brand-chatgpt': 'chatgpt',
13
+ 'agent-brand-figma': 'figma',
14
+ 'agent-brand-lovable': 'lovable',
15
+ 'agent-brand-replit': 'replit',
13
16
  'agent-brand-rovo': 'rovo'
14
17
  };
15
18
 
19
+ /**
20
+ * Brands that prefer the account's real avatar over their fixed glyph when the invoking profile
21
+ * has one. Claude/ChatGPT/Rovo intentionally keep their fixed glyph always (see `AGENT_KIND_ICONS`
22
+ * in `contributorAvatarRenderer.ts`).
23
+ */
24
+ const AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit']);
25
+
16
26
  /** Known external agent types emitted by Confluence's agent identification service that carry
17
27
  * no `@atlaskit/agent-color` brand — a generic labelled fallback. */
18
28
  const EXTERNAL_AGENT_NAMES = {
@@ -53,19 +63,24 @@ const resolveUser = (userId, profilesByAccountId) => {
53
63
  const resolveAgent = (attribution, profilesByAccountId) => {
54
64
  var _attribution$agentTyp2, _attribution$agentId2;
55
65
  const agentType = (_attribution$agentTyp2 = attribution.agentType) === null || _attribution$agentTyp2 === void 0 ? void 0 : _attribution$agentTyp2.trim().toLowerCase();
66
+ // `agentType` may be a named id (e.g. `mcp_lovable_agent`) or a display name (e.g. `lovable`).
56
67
  const brand = agentType ? getThirdPartyAgentColor({
68
+ agentNamedId: agentType,
57
69
  agentName: agentType
58
70
  }) : undefined;
59
71
  const diffBrand = brand ? SHOW_DIFF_AGENT_BRANDS[brand.scheme] : undefined;
72
+ const agentId = (_attribution$agentId2 = attribution.agentId) === null || _attribution$agentId2 === void 0 ? void 0 : _attribution$agentId2.trim();
73
+ const agentProfile = agentId ? profilesByAccountId.get(agentId) : undefined;
60
74
  if (diffBrand && brand) {
61
75
  return {
62
76
  agentKind: diffBrand,
63
77
  kind: 'agent',
64
- name: brand.name
78
+ name: brand.name,
79
+ ...(AVATAR_ELIGIBLE_BRANDS.has(diffBrand) && agentProfile !== null && agentProfile !== void 0 && agentProfile.avatarUrl ? {
80
+ avatarUrl: agentProfile.avatarUrl
81
+ } : {})
65
82
  };
66
83
  }
67
- const agentId = (_attribution$agentId2 = attribution.agentId) === null || _attribution$agentId2 === void 0 ? void 0 : _attribution$agentId2.trim();
68
- const agentProfile = agentId ? profilesByAccountId.get(agentId) : undefined;
69
84
  if (agentProfile) {
70
85
  return {
71
86
  ...(agentProfile.agentBrand ? {
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { UNSAFE_expValNoExposure } from '@atlaskit/platform-feature-experiments/unsafe-exp-val-no-exposure';
3
3
  import { fg } from '@atlaskit/platform-feature-flags/fg';
4
- import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
4
  import { areAttributionColorGatesEnabled, resolveContributors } from './pm-plugins/decorations/colorSchemes/attributions';
6
5
  import { getDeletedWidgets } from './pm-plugins/getDeletedWidgets';
7
6
  import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
@@ -67,12 +66,10 @@ export const showDiffPlugin = ({
67
66
  showDiff: params => ({
68
67
  tr
69
68
  }) => {
70
- if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
71
- var _api$userIntent;
72
- api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('viewingDiff')({
73
- tr
74
- });
75
- }
69
+ var _api$userIntent;
70
+ api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('viewingDiff')({
71
+ tr
72
+ });
76
73
  const reveal = resolveReveal(params === null || params === void 0 ? void 0 : params.reveal, editorView);
77
74
 
78
75
  // Capture snapshot BEFORE transaction dispatch (last moment outgoing DOM exists).
@@ -99,15 +96,13 @@ export const showDiffPlugin = ({
99
96
  hideDiff: ({
100
97
  tr
101
98
  }) => {
99
+ var _api$userIntent2;
102
100
  if (editorView) {
103
101
  cancelReveal(editorView);
104
102
  }
105
- if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
106
- var _api$userIntent2;
107
- api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default')({
108
- tr
109
- });
110
- }
103
+ api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default')({
104
+ tr
105
+ });
111
106
  return tr.setMeta(showDiffPluginKey, {
112
107
  steps: [],
113
108
  stepAttributions: [],
@@ -141,9 +136,6 @@ export const showDiffPlugin = ({
141
136
  }];
142
137
  },
143
138
  contentComponent: () => {
144
- if (!expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
145
- return null;
146
- }
147
139
  // Rendered here sharing decoration anchor span DOM context (tags mount separately).
148
140
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(IndicatorBarContentComponent, {
149
141
  api: api
@@ -154,9 +146,7 @@ export const showDiffPlugin = ({
154
146
  return {
155
147
  isDisplayingChanges: false,
156
148
  activeIndex: undefined,
157
- ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
158
- diffDescriptors: []
159
- } : {})
149
+ diffDescriptors: []
160
150
  };
161
151
  }
162
152
  const pluginState = showDiffPluginKey.getState(editorState);
@@ -165,11 +155,9 @@ export const showDiffPlugin = ({
165
155
  isDisplayingChanges: decorationCount.length > 0,
166
156
  activeIndex: pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex,
167
157
  numberOfChanges: decorationCount.length,
168
- ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
169
- contributorTags: pluginState === null || pluginState === void 0 ? void 0 : pluginState.contributorTags,
170
- diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors,
171
- showIndicators: pluginState === null || pluginState === void 0 ? void 0 : pluginState.showIndicators
172
- } : {})
158
+ contributorTags: pluginState === null || pluginState === void 0 ? void 0 : pluginState.contributorTags,
159
+ diffDescriptors: pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffDescriptors,
160
+ showIndicators: pluginState === null || pluginState === void 0 ? void 0 : pluginState.showIndicators
173
161
  };
174
162
  }
175
163
  };
@@ -19,7 +19,7 @@
19
19
 
20
20
  /** Branded agent presentations supported by contributor tags. */
21
21
 
22
- export const DIFF_AGENT_BRANDS = new Set(['rovo', 'claude', 'chatgpt']);
22
+ export const DIFF_AGENT_BRANDS = new Set(['rovo', 'claude', 'chatgpt', 'figma', 'lovable', 'replit']);
23
23
 
24
24
  /** The brand id `@atlaskit/agent-color` registers each `AgentBrandColorScheme` under. */
25
25
 
@@ -5,11 +5,11 @@ import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
5
5
  import { getContributorTagIcon } from './contributorTagIcons';
6
6
 
7
7
  /**
8
- * Agent kinds with a custom contributor-tag icon. The `satisfies` clause fails the build if a
9
- * `DiffAgentBrand` is missing an icon here; `ASSERT_DIFF_AGENT_BRANDS_ARE_REGISTERED` in
10
- * `showDiffPluginType.ts` similarly fails the build if a brand has no `@atlaskit/agent-color`
11
- * colour scheme. The declared type stays the wider `TagContributor['agentKind']` so indexing below
12
- * (with `'identified' | 'external'` in play too) stays safely partial.
8
+ * Agent kinds with a custom contributor-tag icon. Figma/Lovable/Replit have no entry here — they
9
+ * always render the real avatar `resolveDiffContributors` supplies, falling back to the generic
10
+ * `aiAgent` glyph (see `showContributorIcon`) on load failure. The declared type stays the wider
11
+ * `TagContributor['agentKind']` so indexing below (with `'identified' | 'external'` in play too)
12
+ * stays safely partial.
13
13
  */
14
14
  const AGENT_KIND_ICONS = {
15
15
  claude: 'claude',
@@ -17,6 +17,14 @@ const AGENT_KIND_ICONS = {
17
17
  rovo: 'rovoHex'
18
18
  };
19
19
 
20
+ /**
21
+ * Brands that always render their fixed glyph, even when the contributor also carries an
22
+ * `avatarUrl`. Figma/Lovable/Replit are excluded here and use the real avatar when
23
+ * `resolveDiffContributors` supplies one, falling back to the generic `aiAgent` glyph on load
24
+ * failure.
25
+ */
26
+ const FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt', 'rovo']);
27
+
20
28
  /** The size `@atlaskit/avatar`'s `xxsmall` rendered at. */
21
29
  const AVATAR_SIZE = AVATAR_SIZES.xxsmall;
22
30
  /** `xxsmall` also carried a `space.025` margin — the same 2px — which is where the ring is painted. */
@@ -108,13 +116,15 @@ export const contributorAvatarRenderer = ({
108
116
  shape.appendChild(fallback);
109
117
  return;
110
118
  }
111
- shape.appendChild(getContributorTagIcon((_AGENT_KIND_ICONS = AGENT_KIND_ICONS[(_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external']) !== null && _AGENT_KIND_ICONS !== void 0 ? _AGENT_KIND_ICONS : 'aiAgent', doc));
119
+ const icon = (_AGENT_KIND_ICONS = AGENT_KIND_ICONS[(_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external']) !== null && _AGENT_KIND_ICONS !== void 0 ? _AGENT_KIND_ICONS : 'aiAgent';
120
+ shape.appendChild(getContributorTagIcon(icon, doc));
112
121
  };
113
122
  if (contributor.avatarUrl) {
114
123
  var _contributor$agentKin2;
115
- // Known brands use their fixed glyph even when the profile also has an avatar URL.
116
- const brandedAgentIcon = isAgent ? AGENT_KIND_ICONS[(_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : 'external'] : undefined;
117
- if (brandedAgentIcon) {
124
+ // Claude/ChatGPT/Rovo always use their fixed glyph, even when the profile also has an
125
+ // avatar URL. Other agents (e.g. Figma/Lovable/Replit) and users prefer the real avatar.
126
+ const usesFixedGlyph = isAgent && FIXED_GLYPH_AGENT_KINDS.has((_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : 'external');
127
+ if (usesFixedGlyph) {
118
128
  showContributorIcon();
119
129
  } else {
120
130
  image = doc.createElement('img');
@@ -25,6 +25,15 @@ const getTagAccent = ({
25
25
  const chatgptBrandColor = getThirdPartyAgentColor({
26
26
  agentName: 'chatgpt'
27
27
  });
28
+ const figmaBrandColor = getThirdPartyAgentColor({
29
+ agentName: 'figma'
30
+ });
31
+ const lovableBrandColor = getThirdPartyAgentColor({
32
+ agentName: 'lovable'
33
+ });
34
+ const replitBrandColor = getThirdPartyAgentColor({
35
+ agentName: 'replit'
36
+ });
28
37
 
29
38
  /** Brand accents for agent kinds with no ADS token match. New agents opt in by adding an entry. */
30
39
  const AGENT_KIND_ACCENT_OVERRIDES = {
@@ -37,6 +46,24 @@ const AGENT_KIND_ACCENT_OVERRIDES = {
37
46
  background: chatgptBrandColor.bold,
38
47
  text: chatgptBrandColor.boldText
39
48
  }
49
+ } : {}),
50
+ ...(figmaBrandColor ? {
51
+ figma: {
52
+ background: figmaBrandColor.bold,
53
+ text: figmaBrandColor.boldText
54
+ }
55
+ } : {}),
56
+ ...(lovableBrandColor ? {
57
+ lovable: {
58
+ background: lovableBrandColor.bold,
59
+ text: lovableBrandColor.boldText
60
+ }
61
+ } : {}),
62
+ ...(replitBrandColor ? {
63
+ replit: {
64
+ background: replitBrandColor.bold,
65
+ text: replitBrandColor.boldText
66
+ }
40
67
  } : {})
41
68
  };
42
69
 
@@ -330,8 +357,9 @@ export class ContributorTagController {
330
357
  stackIndex
331
358
  });
332
359
  if (index < stack.length - 1) {
333
- // Overlaps the leading avatar of a connected pair onto the one it sits in front of.
334
- avatar.element.style.setProperty('margin-inline-end', "var(--ds-space-negative-050, -4px)");
360
+ // Sits the leading avatar of a connected pair flush against the one behind it, with
361
+ // no overlap and no extra gap.
362
+ avatar.element.style.setProperty('margin-inline-end', '0');
335
363
  }
336
364
  container.appendChild(avatar.element);
337
365
  this.avatars.push(avatar);
@@ -25,8 +25,8 @@ const AI_AGENT_ICON_SVG = `<svg width="12" height="12" fill="none" viewBox="0 0
25
25
  /** `RovoHexIcon` from `@atlaskit/logo/rovo-hex/icon`, at the 16px `xxsmall` renders. */
26
26
  const ROVO_HEX_ICON_SVG = `<svg width="16" height="16" viewBox="0 0 24 24" role="presentation" style="display:block"><path fill="#1868db" fill-rule="evenodd" d="m13.227 16.789-7.154 4.169-3.403-1.96a2.72 2.72 0 0 1-1.362-2.355V7.366c0-.973.518-1.87 1.361-2.354l6.044-3.487-.038.114a3.6 3.6 0 0 0-.172 1.088v9.278c0 1.274.68 2.45 1.786 3.085z" clip-rule="evenodd"/><path fill="#6a9a23" fill-rule="evenodd" d="m11.296 15.671-7.193 4.153 6.607 3.812a2.73 2.73 0 0 0 2.676.026l.048-.033a2.73 2.73 0 0 0 1.232-1.525 2.7 2.7 0 0 0 .127-.822v-3.594z" clip-rule="evenodd"/><path fill="#af59e1" fill-rule="evenodd" d="m21.477 5.003-4.404-2.539-5.904 4.89 2.69 1.556a3.56 3.56 0 0 1 1.785 3.086v9.277a3.6 3.6 0 0 1-.21 1.202l6.044-3.486a2.71 2.71 0 0 0 1.362-2.355V7.357c0-.97-.521-1.87-1.363-2.354" clip-rule="evenodd"/><path fill="#fca700" fill-rule="evenodd" d="M12.74 8.266 9.353 6.312V2.718c0-.283.044-.56.127-.821A2.73 2.73 0 0 1 10.71.372V.37a.4.4 0 0 0 .048-.033 2.73 2.73 0 0 1 2.676.026l6.499 3.75z" clip-rule="evenodd"/></svg>`;
27
27
 
28
- /** ClaudeLogo from ai-mate/studio-browse-kit, inset to fit the agent hexagon. */
29
- const CLAUDE_ICON_SVG = `<svg width="12" height="12" viewBox="8 8 32 32" role="presentation" style="display:block"><path fill="#FFFFFF" d="M14.2785 29.274L20.5732 25.7445L20.6785 25.4369L20.5732 25.2669H20.2653L19.2122 25.2021L15.6152 25.105L12.4962 24.9755L9.47443 24.8136L8.71291 24.6517L8 23.7126L8.07291 23.2431L8.71291 22.8141L9.62835 22.895L11.6537 23.0326L14.6916 23.2431L16.8952 23.3726L20.16 23.7126H20.6785L20.7514 23.5022L20.5732 23.3726L20.4354 23.2431L17.2922 21.1141L13.8896 18.8636L12.1073 17.5684L11.1433 16.9127L10.6572 16.2975L10.4466 14.9537L11.3215 13.9904L12.4962 14.0713L12.7959 14.1523L13.9868 15.067L16.5306 17.0342L19.8522 19.4789L20.3382 19.8836L20.5327 19.746L20.557 19.6489L20.3382 19.2846L18.5316 16.0223L16.6035 12.7033L15.7448 11.3271L15.518 10.5014C15.437 10.1614 15.3803 9.87807 15.3803 9.52998L16.3767 8.17809L16.9276 8L18.2562 8.17809L18.8152 8.6638L19.6415 10.55L20.9782 13.5209L23.0522 17.5603L23.6597 18.7584L23.9838 19.8674L24.1053 20.2074H24.3159V20.0132L24.4861 17.7384L24.802 14.9456L25.1099 11.3514L25.2152 10.3395L25.7175 9.12522L26.7139 8.46952L27.4916 8.84189L28.1316 9.75664L28.0425 10.3476L27.6618 12.8166L26.9165 16.6861L26.4304 19.2765H26.7139L27.038 18.9527L28.3504 17.2122L30.5539 14.4599L31.5261 13.3671L32.6603 12.1609L33.3894 11.5861H34.7666L35.7792 13.0918L35.3256 14.6461L33.9079 16.4432L32.7332 17.9651L31.0481 20.2317L29.9949 22.045L30.0922 22.1907L30.3433 22.1665L34.1509 21.3569L36.2086 20.9846L38.6633 20.5636L39.7732 21.0817L39.8947 21.6079L39.4572 22.6845L36.8324 23.3322L33.7539 23.9474L29.1686 25.0321L29.1119 25.0726L29.1767 25.1536L31.2425 25.3478L32.1256 25.3964H34.2886L38.3149 25.6959L39.3681 26.3921L40 27.2421L39.8947 27.8897L38.2744 28.7154L36.0871 28.1973L30.9833 26.9831L29.2334 26.5459H28.9904V26.6916L30.4486 28.1164L33.122 30.5287L36.4678 33.6372L36.638 34.4063L36.2086 35.0134L35.7549 34.9486L32.8142 32.7387L31.68 31.743L29.1119 29.5816H28.9418V29.8082L29.5332 30.6744L32.6603 35.3696L32.8223 36.8105L32.5954 37.28L31.7853 37.5634L30.8942 37.4015L29.0633 34.8353L27.1757 31.9454L25.6527 29.3549L25.4663 29.4602L24.5671 39.1338L24.1458 39.6276L23.1737 40L22.3635 39.3848L21.9342 38.3891L22.3635 36.422L22.882 33.8558L23.3033 31.8158L23.6841 29.2821L23.9109 28.4402L23.8947 28.3835L23.7084 28.4078L21.7965 31.0306L18.8881 34.9567L16.5873 37.4177L16.0365 37.6362L15.0805 37.1424L15.1696 36.2601L15.7043 35.4748L18.8881 31.4273L20.8081 28.9178L22.0476 27.4688L22.0395 27.2583H21.9666L13.5089 32.7468L12.002 32.9411L11.3539 32.3339L11.4349 31.3382L11.7428 31.0144L14.2866 29.2659L14.2785 29.274Z"/></svg>`;
28
+ /** Claude hexagon lockup from the brand asset: the hexagon and knot glyph both baked in. */
29
+ const CLAUDE_ICON_SVG = `<svg width="16" height="18" viewBox="0 0 16 18" fill="none" role="presentation" style="display:block"><path fill="#D97757" d="M14.5007 3.28903L9.50384 0.402344C8.5736 -0.13506 7.42701 -0.134016 6.49774 0.405082L1.49458 3.30759C0.569434 3.8443 0 4.83297 0 5.90253V11.1804C0 12.2519 0.571497 13.2421 1.49931 13.7781L6.49931 16.6666C7.42787 17.203 8.57213 17.203 9.50069 16.6666L14.5007 13.7781C15.4285 13.2421 16 12.2519 16 11.1804V5.88671C16 4.8152 15.4285 3.82504 14.5007 3.28903Z"/><path fill="#FAF9F6" d="M5.19791 10.055L7.0123 9.03681L7.04267 8.94806L7.0123 8.89907H6.92357L6.62 8.88034L5.58321 8.85232L4.68418 8.815L3.81317 8.76826L3.59367 8.72158L3.38818 8.4507L3.4092 8.31526L3.59367 8.1915L3.85754 8.21485L4.44133 8.25455L5.317 8.31526L5.95216 8.35262L6.89321 8.4507H7.04267L7.06368 8.38999L7.0123 8.35262L6.97261 8.31526L6.06658 7.70112L5.08582 7.05196L4.5721 6.67834L4.29422 6.48919L4.15411 6.31172L4.09339 5.92409L4.34559 5.64621L4.68418 5.66956L4.77058 5.69291L5.11384 5.95678L5.84708 6.52422L6.80448 7.22943L6.94459 7.34618L7.00063 7.30649L7.00763 7.27846L6.94459 7.17338L6.42385 6.23233L5.86809 5.27492L5.62057 4.87795L5.55519 4.63977C5.53183 4.54169 5.51549 4.45996 5.51549 4.35956L5.80271 3.96959L5.9615 3.91821L6.34446 3.96959L6.50558 4.10969L6.74377 4.65378L7.12907 5.51077L7.72686 6.676L7.90199 7.0216L7.99539 7.34152L8.0304 7.43959H8.09113V7.38354L8.14018 6.72737L8.23124 5.92175L8.31999 4.88496L8.35032 4.59307L8.49511 4.24279L8.78232 4.05365L9.00649 4.16107L9.19098 4.42494L9.16533 4.5954L9.05555 5.30762L8.84073 6.42381L8.70062 7.17105H8.78232L8.87574 7.07764L9.25401 6.57559L9.88922 5.78165L10.1694 5.4664L10.4963 5.11847L10.7065 4.95267H11.1035L11.3953 5.38701L11.2646 5.83535L10.8559 6.35375L10.5173 6.79276L10.0316 7.4466L9.72807 7.96966L9.7561 8.0117L9.82849 8.00469L10.926 7.77118L11.5191 7.66376L12.2266 7.54233L12.5466 7.69178L12.5816 7.84356L12.4555 8.15414L11.6989 8.34095L10.8116 8.51842L9.48985 8.83136L9.4735 8.84303L9.49223 8.86637L10.0877 8.92241L10.3422 8.93639H10.9657L12.1262 9.02283L12.4298 9.2236L12.612 9.46881L12.5816 9.6556L12.1146 9.89382L11.4841 9.74434L10.013 9.3941L9.50858 9.26797H9.43849V9.31004L9.85882 9.721L10.6294 10.4169L11.5938 11.3136L11.6429 11.5354L11.5191 11.7106L11.3884 11.6918L10.5407 11.0544L10.2137 10.7672L9.4735 10.1436H9.42451V10.209L9.59495 10.4589L10.4963 11.8133L10.543 12.2289L10.4776 12.3644L10.2441 12.4461L9.98726 12.3994L9.45952 11.6592L8.91544 10.8255L8.47645 10.0783L8.42271 10.1086L8.16352 12.8991L8.04207 13.0416L7.76188 13.149L7.52837 12.9715L7.40461 12.6843L7.52837 12.1168L7.67781 11.3766L7.79925 10.7881L7.90899 10.0573L7.97438 9.81443L7.96971 9.79808L7.916 9.80507L7.36491 10.5617L6.5266 11.6942L5.86342 12.4041L5.70463 12.4671L5.42909 12.3247L5.45477 12.0702L5.60889 11.8436L6.5266 10.6761L7.08002 9.95217L7.4373 9.53421L7.43497 9.47349H7.41395L4.97607 11.0567L4.54174 11.1127L4.35493 10.9376L4.37828 10.6504L4.46702 10.557L5.20024 10.0526L5.19791 10.055Z"/></svg>`;
30
30
 
31
31
  /** ChatGPT hexagon lockup from the brand asset: the hexagon and knot glyph both baked in. */
32
32
  const CHATGPT_ICON_SVG = `<svg width="16" height="18" viewBox="0 0 16 18" fill="none" role="presentation" style="display:block"><path fill="#14120B" d="M14.5007 3.289L9.50384 0.402314C8.5736 -0.13509 7.42701 -0.134047 6.49774 0.405051L1.49458 3.30756C0.569434 3.84427 0 4.83294 0 5.9025V11.1804C0 12.2519 0.571497 13.2421 1.49931 13.7781L6.49931 16.6666C7.42787 17.203 8.57213 17.203 9.50069 16.6666L14.5007 13.7781C15.4285 13.2421 16 12.2519 16 11.1804V5.88668C16 4.81517 15.4285 3.82501 14.5007 3.289Z"/><path fill="white" d="M12.255 7.39338C12.4813 6.54514 12.2618 5.60258 11.5963 4.93713C10.9309 4.2717 9.9884 4.05217 9.1401 4.27852C8.51863 3.65837 7.59268 3.37721 6.68362 3.62082C5.77456 3.86436 5.11322 4.57087 4.88512 5.41867C4.03733 5.64676 3.33082 6.30819 3.08727 7.21717C2.84372 8.12623 3.12482 9.05218 3.74503 9.67365C3.51868 10.5219 3.73823 11.4645 4.40366 12.1299C5.06909 12.7953 6.01159 13.0149 6.85992 12.7885C7.48137 13.4087 8.4074 13.6898 9.31638 13.4463C10.2254 13.2027 10.8868 12.4962 11.1149 11.6485C11.9627 11.4203 12.6692 10.7589 12.9127 9.84993C13.1563 8.94089 12.8752 8.01491 12.255 7.39347V7.39338ZM11.1878 5.34578C11.6387 5.79673 11.8247 6.41226 11.7457 6.99902L9.62799 5.77632C9.53872 5.72478 9.42871 5.72478 9.3395 5.77632L6.85992 7.20789V6.26917C6.85992 6.20333 6.89519 6.1417 6.95226 6.10877L8.84042 5.01867C9.58854 4.60079 10.5519 4.7099 11.1878 5.34578H11.1878ZM8.00001 7.21703L9.14016 7.87529V9.19183L8.00001 9.85009L6.85984 9.19183V7.87529L8.00001 7.21703ZM5.37616 6.04832C5.38831 5.19153 5.96453 4.41177 6.83319 4.17899C7.44917 4.01397 8.07524 4.16069 8.54389 4.52241L6.42609 5.74505C6.33682 5.79656 6.28184 5.89186 6.28184 5.99489V8.85803L5.4689 8.38867C5.41189 8.35573 5.37616 8.29433 5.37616 8.22846V6.04826V6.04832ZM3.64542 7.36674C3.81044 6.75079 4.25056 6.28191 4.79817 6.05694V8.50232C4.79817 8.60534 4.85315 8.70061 4.94241 8.75216L7.42202 10.1837L6.60904 10.6531C6.55203 10.686 6.48098 10.6862 6.42397 10.6533L4.53581 9.56321C3.79984 9.12427 3.41272 8.23534 3.64542 7.36674ZM4.81224 11.7213C4.36129 11.2704 4.17534 10.6549 4.25429 10.0681L6.37201 11.2908C6.4613 11.3423 6.57129 11.3423 6.6605 11.2908L9.1401 9.85923V10.7979C9.1401 10.8638 9.10483 10.9254 9.04774 10.9584L7.15958 12.0485C6.41145 12.4663 5.44809 12.3572 4.81215 11.7213H4.81224ZM10.6238 11.0188C10.6117 11.8756 10.0355 12.6554 9.1668 12.8881C8.55083 13.0532 7.92476 12.9064 7.45613 12.5447L9.57391 11.322C9.6632 11.2705 9.71816 11.1753 9.71816 11.0722V8.20906L10.5311 8.67845C10.5881 8.71139 10.6238 8.77279 10.6238 8.83866V11.0189V11.0188ZM12.3546 9.70035C12.1896 10.3163 11.7494 10.7852 11.2018 11.0101V8.5648C11.2018 8.46178 11.1469 8.36648 11.0576 8.31496L8.57798 6.88339L9.39095 6.41401C9.44796 6.38107 9.51902 6.38085 9.57603 6.41378L11.4642 7.50388C12.2002 7.94285 12.5873 8.83178 12.3546 9.70035Z"/></svg>`;