@atlaskit/editor-plugin-show-diff 14.5.2 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -6
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +3 -9
- package/dist/cjs/pm-plugins/calculateDiff/smart/classifySmartChanges.js +1 -2
- package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +21 -4
- package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +6 -56
- package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +6 -20
- package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +4 -6
- package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -2
- package/dist/cjs/pm-plugins/decorations/createContributorTagWidget.js +14 -29
- package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +1 -2
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +2 -25
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +1 -2
- package/dist/cjs/pm-plugins/main.js +4 -4
- package/dist/cjs/showDiffPlugin.js +4 -5
- package/dist/cjs/ui/ContributorTag/buildContributorTagDom.js +122 -0
- package/dist/cjs/ui/ContributorTag/contributorAvatarRenderer.js +140 -0
- package/dist/cjs/ui/ContributorTag/contributorTagController.js +500 -0
- package/dist/cjs/ui/ContributorTag/contributorTagIcons.js +46 -0
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +3 -5
- package/dist/es2019/pm-plugins/calculateDiff/smart/classifySmartChanges.js +1 -2
- package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +20 -3
- package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +6 -55
- package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +14 -26
- package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +4 -6
- package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -2
- package/dist/es2019/pm-plugins/decorations/createContributorTagWidget.js +16 -30
- package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +1 -2
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +2 -17
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +1 -2
- package/dist/es2019/pm-plugins/main.js +4 -4
- package/dist/es2019/showDiffPlugin.js +4 -5
- package/dist/es2019/ui/ContributorTag/buildContributorTagDom.js +110 -0
- package/dist/es2019/ui/ContributorTag/contributorAvatarRenderer.js +136 -0
- package/dist/es2019/ui/ContributorTag/contributorTagController.js +403 -0
- package/dist/es2019/ui/ContributorTag/contributorTagIcons.js +40 -0
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +3 -9
- package/dist/esm/pm-plugins/calculateDiff/smart/classifySmartChanges.js +1 -2
- package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +21 -4
- package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +6 -57
- package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +7 -20
- package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +4 -6
- package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -2
- package/dist/esm/pm-plugins/decorations/createContributorTagWidget.js +15 -30
- package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +1 -2
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +2 -25
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +1 -2
- package/dist/esm/pm-plugins/main.js +4 -4
- package/dist/esm/showDiffPlugin.js +4 -5
- package/dist/esm/ui/ContributorTag/buildContributorTagDom.js +115 -0
- package/dist/esm/ui/ContributorTag/contributorAvatarRenderer.js +135 -0
- package/dist/esm/ui/ContributorTag/contributorTagController.js +493 -0
- package/dist/esm/ui/ContributorTag/contributorTagIcons.js +40 -0
- package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +3 -3
- package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +2 -2
- package/dist/types/pm-plugins/decorations/colorSchemes/schemes.d.ts +1 -1
- package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +13 -16
- package/dist/types/pm-plugins/decorations/createContributorTagWidget.d.ts +11 -9
- package/dist/types/pm-plugins/main.d.ts +1 -2
- package/dist/types/ui/ContributorTag/buildContributorTagDom.d.ts +25 -0
- package/dist/types/ui/ContributorTag/contributorAvatarRenderer.d.ts +22 -0
- package/dist/types/ui/ContributorTag/contributorTagController.d.ts +85 -0
- package/dist/types/ui/ContributorTag/contributorTagIcons.d.ts +12 -0
- package/package.json +9 -13
- package/dist/cjs/ui/ContributorTag/ContributorTag.compiled.css +0 -29
- package/dist/cjs/ui/ContributorTag/ContributorTag.js +0 -383
- package/dist/cjs/ui/ContributorTag/ContributorTagWidget.js +0 -50
- package/dist/es2019/ui/ContributorTag/ContributorTag.compiled.css +0 -29
- package/dist/es2019/ui/ContributorTag/ContributorTag.js +0 -312
- package/dist/es2019/ui/ContributorTag/ContributorTagWidget.js +0 -43
- package/dist/esm/ui/ContributorTag/ContributorTag.compiled.css +0 -29
- package/dist/esm/ui/ContributorTag/ContributorTag.js +0 -375
- package/dist/esm/ui/ContributorTag/ContributorTagWidget.js +0 -43
- package/dist/types/ui/ContributorTag/ContributorTag.d.ts +0 -37
- package/dist/types/ui/ContributorTag/ContributorTagWidget.d.ts +0 -22
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import { bindAll } from 'bind-event-listener';
|
|
3
|
+
import { VanillaTooltip } from '@atlaskit/editor-common/vanilla-tooltip';
|
|
4
|
+
import { getAccentTokens } from '../../pm-plugins/decorations/colorSchemes/factory';
|
|
5
|
+
import { colorSchemeRegistry } from '../../pm-plugins/decorations/colorSchemes/schemes';
|
|
6
|
+
import { buildContributorTagDom, MIN_TAG_WIDTH } from './buildContributorTagDom';
|
|
7
|
+
import { contributorAvatarRenderer } from './contributorAvatarRenderer';
|
|
8
|
+
import { contributorTagMessages } from './messages';
|
|
9
|
+
const getContributorName = (contributor, formatMessage) => {
|
|
10
|
+
var _contributor$name, _contributor$agentKin;
|
|
11
|
+
const name = (_contributor$name = contributor.name) === null || _contributor$name === void 0 ? void 0 : _contributor$name.trim();
|
|
12
|
+
if (name) {
|
|
13
|
+
return name;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// `agentKind` defaults to `'external'` per the plugin type contract; an unidentified external
|
|
17
|
+
// agent falls back to a generic label rather than rendering a nameless tag.
|
|
18
|
+
if (contributor.kind === 'agent' && ((_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external') === 'external') {
|
|
19
|
+
return formatMessage(contributorTagMessages.externalAgentName);
|
|
20
|
+
}
|
|
21
|
+
return '';
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolves the tag's accent from the same scheme value and token maps the highlight used, so the
|
|
26
|
+
* two can never drift.
|
|
27
|
+
*/
|
|
28
|
+
const getTagAccent = ({
|
|
29
|
+
colorScheme,
|
|
30
|
+
isActive,
|
|
31
|
+
isInserted
|
|
32
|
+
}) => {
|
|
33
|
+
const colors = colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
|
|
34
|
+
const accent = isInserted ? isActive ? colors.insertActiveColor : colors.insertColor : isActive ? colors.deleteActiveColor : colors.deleteColor;
|
|
35
|
+
return getAccentTokens(accent);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** The line the change starts on: topmost of its fragments, leftmost among those. */
|
|
39
|
+
const findChangeStartLine = highlights => {
|
|
40
|
+
let start;
|
|
41
|
+
for (const highlight of highlights) {
|
|
42
|
+
for (const rect of highlight.getClientRects()) {
|
|
43
|
+
if (!start || rect.top < start.top - 1 || Math.abs(rect.top - start.top) <= 1 && rect.left < start.left) {
|
|
44
|
+
start = rect;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return start;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** The contributors a tag draws, keyed so a republished model can be recognised as the same pair. */
|
|
52
|
+
const identityOf = model => [model === null || model === void 0 ? void 0 : model.contributor, model === null || model === void 0 ? void 0 : model.connectedContributor].map(contributor => {
|
|
53
|
+
var _contributor$agentKin2, _contributor$avatarUr;
|
|
54
|
+
return contributor ? `${contributor.kind}:${(_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : ''}:${contributor.name}:${(_contributor$avatarUr = contributor.avatarUrl) !== null && _contributor$avatarUr !== void 0 ? _contributor$avatarUr : ''}` : '';
|
|
55
|
+
}).join('|');
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A small tag naming who made one diff, drawn into the host element its decoration places on the
|
|
59
|
+
* change's first character and positioned above it.
|
|
60
|
+
*
|
|
61
|
+
* The model is resolved from plugin state here rather than passed in, because ProseMirror skips
|
|
62
|
+
* `toDOM` for a widget it reuses: stepping to the next change republishes the tags without redrawing
|
|
63
|
+
* their hosts, so anything the tag reacts to — `isActive` above all — has to arrive through a
|
|
64
|
+
* subscription of its own (EDITOR-8702). Draws nothing when this diff has no tag, which is the case
|
|
65
|
+
* for the deleted half of a replacement: that half is folded into the inline tag.
|
|
66
|
+
*/
|
|
67
|
+
export class ContributorTagController {
|
|
68
|
+
constructor(options) {
|
|
69
|
+
_defineProperty(this, "avatars", []);
|
|
70
|
+
/** Guards a deferred bind that a later model change has already superseded. */
|
|
71
|
+
_defineProperty(this, "bindToken", 0);
|
|
72
|
+
_defineProperty(this, "fullLabel", '');
|
|
73
|
+
_defineProperty(this, "isDestroyed", false);
|
|
74
|
+
_defineProperty(this, "isHighlightHovered", false);
|
|
75
|
+
_defineProperty(this, "isHoveredOrFocused", false);
|
|
76
|
+
_defineProperty(this, "unbindHighlights", []);
|
|
77
|
+
this.options = options;
|
|
78
|
+
}
|
|
79
|
+
mount(host) {
|
|
80
|
+
var _this$options$api$sho, _this$options$api, _sharedState$currentS;
|
|
81
|
+
this.host = host;
|
|
82
|
+
const {
|
|
83
|
+
sharedState
|
|
84
|
+
} = (_this$options$api$sho = (_this$options$api = this.options.api) === null || _this$options$api === void 0 ? void 0 : _this$options$api.showDiff) !== null && _this$options$api$sho !== void 0 ? _this$options$api$sho : {};
|
|
85
|
+
this.unsubscribe = sharedState === null || sharedState === void 0 ? void 0 : sharedState.onChange(({
|
|
86
|
+
nextSharedState
|
|
87
|
+
}) => {
|
|
88
|
+
this.applyModel(this.findModel(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.contributorTags));
|
|
89
|
+
});
|
|
90
|
+
this.applyModel(this.findModel(sharedState === null || sharedState === void 0 ? void 0 : (_sharedState$currentS = sharedState.currentState()) === null || _sharedState$currentS === void 0 ? void 0 : _sharedState$currentS.contributorTags));
|
|
91
|
+
}
|
|
92
|
+
destroy() {
|
|
93
|
+
var _this$unsubscribe;
|
|
94
|
+
this.isDestroyed = true;
|
|
95
|
+
(_this$unsubscribe = this.unsubscribe) === null || _this$unsubscribe === void 0 ? void 0 : _this$unsubscribe.call(this);
|
|
96
|
+
this.unsubscribe = undefined;
|
|
97
|
+
this.teardownTag();
|
|
98
|
+
this.host = undefined;
|
|
99
|
+
}
|
|
100
|
+
findModel(tags) {
|
|
101
|
+
return tags === null || tags === void 0 ? void 0 : tags.find(tag => tag.diffId === this.options.diffId);
|
|
102
|
+
}
|
|
103
|
+
applyModel(next) {
|
|
104
|
+
if (this.isDestroyed || next === this.model) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const previous = this.model;
|
|
108
|
+
this.model = next;
|
|
109
|
+
const {
|
|
110
|
+
host
|
|
111
|
+
} = this;
|
|
112
|
+
if (!next || !host) {
|
|
113
|
+
this.teardownTag();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!this.dom) {
|
|
117
|
+
this.dom = buildContributorTagDom(host.ownerDocument);
|
|
118
|
+
this.bindTag(this.dom);
|
|
119
|
+
host.appendChild(this.dom.root);
|
|
120
|
+
}
|
|
121
|
+
if (!previous || identityOf(previous) !== identityOf(next)) {
|
|
122
|
+
this.renderAvatars(next);
|
|
123
|
+
}
|
|
124
|
+
this.renderLabels(next);
|
|
125
|
+
this.applyAccent(next);
|
|
126
|
+
this.syncHighlightBindings(next);
|
|
127
|
+
this.applyStyles();
|
|
128
|
+
this.syncTooltip();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Takes the tag's DOM down, keeping the subscription so a republished model redraws it. */
|
|
132
|
+
teardownTag() {
|
|
133
|
+
var _this$unbindTag, _this$tooltip, _this$dom;
|
|
134
|
+
this.unbindHighlightState();
|
|
135
|
+
this.boundSelector = undefined;
|
|
136
|
+
(_this$unbindTag = this.unbindTag) === null || _this$unbindTag === void 0 ? void 0 : _this$unbindTag.call(this);
|
|
137
|
+
this.unbindTag = undefined;
|
|
138
|
+
(_this$tooltip = this.tooltip) === null || _this$tooltip === void 0 ? void 0 : _this$tooltip.destroy();
|
|
139
|
+
this.tooltip = undefined;
|
|
140
|
+
this.tooltipContent = undefined;
|
|
141
|
+
this.avatars.forEach(avatar => avatar.destroy());
|
|
142
|
+
this.avatars = [];
|
|
143
|
+
(_this$dom = this.dom) === null || _this$dom === void 0 ? void 0 : _this$dom.root.remove();
|
|
144
|
+
this.dom = undefined;
|
|
145
|
+
this.maxWidthPx = undefined;
|
|
146
|
+
this.isHoveredOrFocused = false;
|
|
147
|
+
// Both hover flags belong to the listeners just unbound: a republished model rebinds them, and
|
|
148
|
+
// stale `true` would draw the tag as visible with the pointer nowhere near it.
|
|
149
|
+
this.isHighlightHovered = false;
|
|
150
|
+
}
|
|
151
|
+
bindTag({
|
|
152
|
+
tag
|
|
153
|
+
}) {
|
|
154
|
+
const setHoveredOrFocused = isHoveredOrFocused => () => {
|
|
155
|
+
this.isHoveredOrFocused = isHoveredOrFocused;
|
|
156
|
+
this.applyStyles();
|
|
157
|
+
};
|
|
158
|
+
this.unbindTag = bindAll(tag, [{
|
|
159
|
+
type: 'mouseover',
|
|
160
|
+
listener: setHoveredOrFocused(true)
|
|
161
|
+
}, {
|
|
162
|
+
type: 'mouseout',
|
|
163
|
+
listener: setHoveredOrFocused(false)
|
|
164
|
+
}, {
|
|
165
|
+
type: 'focus',
|
|
166
|
+
listener: setHoveredOrFocused(true)
|
|
167
|
+
}, {
|
|
168
|
+
type: 'blur',
|
|
169
|
+
listener: setHoveredOrFocused(false)
|
|
170
|
+
}]);
|
|
171
|
+
}
|
|
172
|
+
renderAvatars(model) {
|
|
173
|
+
var _this$dom2;
|
|
174
|
+
const {
|
|
175
|
+
avatars: container
|
|
176
|
+
} = (_this$dom2 = this.dom) !== null && _this$dom2 !== void 0 ? _this$dom2 : {};
|
|
177
|
+
if (!container) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this.avatars.forEach(avatar => avatar.destroy());
|
|
181
|
+
this.avatars = [];
|
|
182
|
+
const doc = container.ownerDocument;
|
|
183
|
+
const {
|
|
184
|
+
background
|
|
185
|
+
} = this.accentOf(model);
|
|
186
|
+
const isPrimaryAgent = model.contributor.kind === 'agent';
|
|
187
|
+
// Resolved by `kind` so a reverse `connectedTo` (an attributed user pointing at its agent)
|
|
188
|
+
// renders identically.
|
|
189
|
+
const user = isPrimaryAgent ? model.connectedContributor : model.contributor;
|
|
190
|
+
const agent = isPrimaryAgent ? model.contributor : model.connectedContributor;
|
|
191
|
+
|
|
192
|
+
// Hand-rolled avatar stack: `@atlaskit/avatar-group` cannot render below 24px and the tag uses
|
|
193
|
+
// 16px avatars.
|
|
194
|
+
const stack = model.connectedContributor ? [...(user ? [{
|
|
195
|
+
contributor: user,
|
|
196
|
+
stackIndex: 1
|
|
197
|
+
}] : []), ...(agent ? [{
|
|
198
|
+
contributor: agent,
|
|
199
|
+
stackIndex: 0
|
|
200
|
+
}] : [])] : [{
|
|
201
|
+
contributor: model.contributor
|
|
202
|
+
}];
|
|
203
|
+
stack.forEach(({
|
|
204
|
+
contributor,
|
|
205
|
+
stackIndex
|
|
206
|
+
}, index) => {
|
|
207
|
+
const avatar = contributorAvatarRenderer({
|
|
208
|
+
contributor,
|
|
209
|
+
doc,
|
|
210
|
+
ringColor: background,
|
|
211
|
+
stackIndex
|
|
212
|
+
});
|
|
213
|
+
if (index < stack.length - 1) {
|
|
214
|
+
// Overlaps the leading avatar of a connected pair onto the one it sits in front of.
|
|
215
|
+
avatar.element.style.setProperty('margin-inline-end', "var(--ds-space-negative-050, -4px)");
|
|
216
|
+
}
|
|
217
|
+
container.appendChild(avatar.element);
|
|
218
|
+
this.avatars.push(avatar);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
renderLabels(model) {
|
|
222
|
+
if (!this.dom) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const {
|
|
226
|
+
formatMessage
|
|
227
|
+
} = this.options.getIntl();
|
|
228
|
+
const isPrimaryAgent = model.contributor.kind === 'agent';
|
|
229
|
+
const primaryName = getContributorName(model.contributor, formatMessage);
|
|
230
|
+
const secondaryName = model.connectedContributor ? getContributorName(model.connectedContributor, formatMessage) : '';
|
|
231
|
+
const agentName = isPrimaryAgent ? primaryName : secondaryName;
|
|
232
|
+
const userName = isPrimaryAgent ? secondaryName : primaryName;
|
|
233
|
+
|
|
234
|
+
// A connected pair only ever shows the agent; the pair is spelled out in the label, because
|
|
235
|
+
// the tag is never wider than the highlight.
|
|
236
|
+
this.dom.name.textContent = model.connectedContributor ? agentName || primaryName : primaryName;
|
|
237
|
+
this.fullLabel = model.connectedContributor ? formatMessage(contributorTagMessages.changedByConnected, {
|
|
238
|
+
agentName,
|
|
239
|
+
userName
|
|
240
|
+
}) : formatMessage(contributorTagMessages.changedBy, {
|
|
241
|
+
name: primaryName
|
|
242
|
+
});
|
|
243
|
+
this.dom.srLabel.textContent = this.fullLabel;
|
|
244
|
+
}
|
|
245
|
+
accentOf(model) {
|
|
246
|
+
var _model$isInserted;
|
|
247
|
+
return getTagAccent({
|
|
248
|
+
colorScheme: model.colorScheme,
|
|
249
|
+
isActive: Boolean(model.isActive),
|
|
250
|
+
isInserted: (_model$isInserted = model.isInserted) !== null && _model$isInserted !== void 0 ? _model$isInserted : true
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
applyAccent(model) {
|
|
254
|
+
if (!this.dom) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const accent = this.accentOf(model);
|
|
258
|
+
this.dom.tag.style.setProperty('background-color', accent.background);
|
|
259
|
+
this.dom.tag.style.setProperty('border-bottom-color', accent.border);
|
|
260
|
+
this.dom.name.style.setProperty('color', accent.text);
|
|
261
|
+
this.avatars.forEach(avatar => avatar.setRingColor(accent.background));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** Width clamp and visibility — the two things that are not carried by the model alone. */
|
|
265
|
+
applyStyles() {
|
|
266
|
+
var _this$model;
|
|
267
|
+
if (!this.dom) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.dom.root.style.setProperty('max-width',
|
|
271
|
+
// Clamped to the highlight's own width, floored at `MIN_TAG_WIDTH` so a one-character
|
|
272
|
+
// change still shows an avatar.
|
|
273
|
+
this.maxWidthPx === undefined ? '' : `max(${Math.round(this.maxWidthPx)}px, ${MIN_TAG_WIDTH})`);
|
|
274
|
+
const isVisible = Boolean((_this$model = this.model) === null || _this$model === void 0 ? void 0 : _this$model.isActive) || this.isHighlightHovered || this.isHoveredOrFocused;
|
|
275
|
+
this.dom.tag.style.setProperty('opacity', isVisible ? '1' : '0');
|
|
276
|
+
this.dom.tag.style.setProperty('pointer-events', isVisible ? 'auto' : 'none');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* The full label is always the tooltip, whether or not the name it draws is clipped: the tag is
|
|
281
|
+
* never wider than the highlight, so a name that fits at one width is ellipsised at the next, and
|
|
282
|
+
* a connected pair spells out a contributor the tag does not show at any width.
|
|
283
|
+
*
|
|
284
|
+
* `VanillaTooltip` has no "set new content" call, so it is rebuilt when the label changes — the
|
|
285
|
+
* shape of `syncVanillaDisabledTooltip` in `mentionNodeView`.
|
|
286
|
+
*/
|
|
287
|
+
syncTooltip() {
|
|
288
|
+
var _this$tooltip2;
|
|
289
|
+
const content = this.dom ? this.fullLabel : undefined;
|
|
290
|
+
if (content === this.tooltipContent) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
(_this$tooltip2 = this.tooltip) === null || _this$tooltip2 === void 0 ? void 0 : _this$tooltip2.destroy();
|
|
294
|
+
this.tooltip = undefined;
|
|
295
|
+
this.tooltipContent = content;
|
|
296
|
+
if (!content || !this.dom) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
this.tooltip = new VanillaTooltip(this.dom.tag, content, undefined,
|
|
300
|
+
// `ak-editor-vanilla-tooltip-default` opts into the shared `VanillaTooltip` look, defined as
|
|
301
|
+
// `vanillaTooltipDefaultStyles` in both EditorContentContainer stylesheets — keep in sync when
|
|
302
|
+
// renaming. Those styles are scoped under `.ProseMirror`, and the tag renders inside it.
|
|
303
|
+
'ak-editor-vanilla-tooltip-default');
|
|
304
|
+
// `VanillaTooltip` sets `aria-describedby` on its trigger, which would announce the label a
|
|
305
|
+
// second time — the visually hidden child already announces it, after the change as design
|
|
306
|
+
// requires.
|
|
307
|
+
this.dom.tag.removeAttribute('aria-describedby');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Observes the highlight this tag describes, for what CSS here cannot see: its hover state (the
|
|
312
|
+
* highlight is a ProseMirror decoration in a different DOM subtree, so listeners are bound
|
|
313
|
+
* imperatively via `data-diff-id`) and the width the tag is clamped to.
|
|
314
|
+
*
|
|
315
|
+
* Deliberately not routed through plugin state: a transaction per pointer move would re-run the
|
|
316
|
+
* memoised decoration calculation.
|
|
317
|
+
*/
|
|
318
|
+
syncHighlightBindings(model) {
|
|
319
|
+
var _model$linkedDiffIds;
|
|
320
|
+
const {
|
|
321
|
+
diffId
|
|
322
|
+
} = this.options;
|
|
323
|
+
const selector = [diffId, ...((_model$linkedDiffIds = model.linkedDiffIds) !== null && _model$linkedDiffIds !== void 0 ? _model$linkedDiffIds : [])].map(id => `[data-diff-id="${id}"]`).join(', ');
|
|
324
|
+
if (selector === this.boundSelector) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
this.boundSelector = selector;
|
|
328
|
+
this.unbindHighlightState();
|
|
329
|
+
|
|
330
|
+
// ProseMirror draws the tag's host in the same pass as the highlights the tag measures, so
|
|
331
|
+
// those may not be in the document yet. A microtask lands once that pass has finished.
|
|
332
|
+
const pendingBind = ++this.bindToken;
|
|
333
|
+
queueMicrotask(() => {
|
|
334
|
+
if (!this.isDestroyed && pendingBind === this.bindToken) {
|
|
335
|
+
this.bindHighlightState(selector);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
bindHighlightState(selector) {
|
|
340
|
+
// Both queries are scoped to this editor's content root, so a tag can only ever bind to the
|
|
341
|
+
// decorations its own plugin instance rendered — another editor on the page, or one nested
|
|
342
|
+
// inside this one, cannot supply the geometry.
|
|
343
|
+
const editorRoot = this.options.getEditorRoot();
|
|
344
|
+
const highlights = editorRoot === null || editorRoot === void 0 ? void 0 : editorRoot.querySelectorAll(selector);
|
|
345
|
+
if (!editorRoot || !(highlights !== null && highlights !== void 0 && highlights.length)) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// The width comes from this tag's OWN decoration; sibling halves of the change are here for
|
|
350
|
+
// hover only.
|
|
351
|
+
const ownElements = Array.from(editorRoot.querySelectorAll(`[data-diff-id="${this.options.diffId}"]`));
|
|
352
|
+
const measure = () => {
|
|
353
|
+
var _findChangeStartLine;
|
|
354
|
+
// Counted by distinct line box, not by client rect: an inline node inside the change (a
|
|
355
|
+
// mention, emoji, date) splits the highlight into several rects on the same line, and
|
|
356
|
+
// treating that as a wrap would drop the width clamp on changes that never wrapped.
|
|
357
|
+
const lineTops = new Set();
|
|
358
|
+
for (const highlight of ownElements) {
|
|
359
|
+
for (const rect of highlight.getClientRects()) {
|
|
360
|
+
lineTops.add(Math.round(rect.top));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// A wrapped change's first line says nothing useful about how wide the tag may be.
|
|
365
|
+
this.maxWidthPx = lineTops.size > 1 ? undefined : (_findChangeStartLine = findChangeStartLine(ownElements)) === null || _findChangeStartLine === void 0 ? void 0 : _findChangeStartLine.width;
|
|
366
|
+
this.applyStyles();
|
|
367
|
+
};
|
|
368
|
+
measure();
|
|
369
|
+
|
|
370
|
+
// An inline element cannot be observed itself (ResizeObserver skips boxes with no principal
|
|
371
|
+
// box), so the block it sits in is observed instead.
|
|
372
|
+
this.resizeObserver = new ResizeObserver(measure);
|
|
373
|
+
for (const parent of new Set(ownElements.map(({
|
|
374
|
+
parentElement
|
|
375
|
+
}) => parentElement))) {
|
|
376
|
+
if (parent) {
|
|
377
|
+
this.resizeObserver.observe(parent);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// `bindAll` takes a single target, and a change can render more than one highlight.
|
|
382
|
+
this.unbindHighlights = Array.from(highlights).map(highlight => bindAll(highlight, [{
|
|
383
|
+
type: 'mouseenter',
|
|
384
|
+
listener: () => {
|
|
385
|
+
this.isHighlightHovered = true;
|
|
386
|
+
this.applyStyles();
|
|
387
|
+
}
|
|
388
|
+
}, {
|
|
389
|
+
type: 'mouseleave',
|
|
390
|
+
listener: () => {
|
|
391
|
+
this.isHighlightHovered = false;
|
|
392
|
+
this.applyStyles();
|
|
393
|
+
}
|
|
394
|
+
}]));
|
|
395
|
+
}
|
|
396
|
+
unbindHighlightState() {
|
|
397
|
+
var _this$resizeObserver;
|
|
398
|
+
(_this$resizeObserver = this.resizeObserver) === null || _this$resizeObserver === void 0 ? void 0 : _this$resizeObserver.disconnect();
|
|
399
|
+
this.resizeObserver = undefined;
|
|
400
|
+
this.unbindHighlights.forEach(unbind => unbind());
|
|
401
|
+
this.unbindHighlights = [];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The icons a contributor tag can draw, as inline SVG.
|
|
3
|
+
*
|
|
4
|
+
* Neither `@atlaskit/icon`, `@atlaskit/icon-lab` nor `@atlaskit/logo` exposes a raw-SVG entry
|
|
5
|
+
* point, so the markup is copied here rather than kept as a React island for three glyphs. Keep in
|
|
6
|
+
* sync with the sources named on each constant.
|
|
7
|
+
*
|
|
8
|
+
* The Rovo hex is the `brand` appearance, whose `--rovo-*-color` variables resolve to `initial` in
|
|
9
|
+
* both themes — the fallbacks below are the rendered colours, so no theme observer is needed.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** `@atlaskit/icon/core/person`, at the 16px the avatar renders it. */
|
|
13
|
+
const PERSON_ICON_SVG = `<svg width="16" height="16" fill="none" viewBox="0 0 16 16" role="presentation" style="display:block"><path fill="currentcolor" fill-rule="evenodd" d="M8 1.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5M4 4a4 4 0 1 1 8 0 4 4 0 0 1-8 0m-2 9a3.75 3.75 0 0 1 3.75-3.75h4.5A3.75 3.75 0 0 1 14 13v2h-1.5v-2a2.25 2.25 0 0 0-2.25-2.25h-4.5A2.25 2.25 0 0 0 3.5 13v2H2z" clip-rule="evenodd"/></svg>`;
|
|
14
|
+
|
|
15
|
+
/** `@atlaskit/icon-lab/core/ai-bot`, at 12px so it fits inside the 16px hexagon. */
|
|
16
|
+
const AI_BOT_ICON_SVG = `<svg width="12" height="12" fill="none" viewBox="0 0 16 16" role="presentation" style="display:block"><path fill="currentcolor" d="M13 5.5a.5.5 0 0 0-.5-.5h-9a.5.5 0 0 0-.5.5V13a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5zm-6.5 2v3H5v-3zm4.5 0v3H9.5v-3zm3.5 1H16V10h-1.5v3a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2v-3H0V8.5h1.5v-3a2 2 0 0 1 2-2h3.75v-2H4V0h4a.75.75 0 0 1 .75.75V3.5h3.75a2 2 0 0 1 2 2z"/></svg>`;
|
|
17
|
+
|
|
18
|
+
/** `RovoHexIcon` from `@atlaskit/logo/rovo-hex/icon`, at the 16px `xxsmall` renders. */
|
|
19
|
+
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>`;
|
|
20
|
+
const markup = {
|
|
21
|
+
aiBot: AI_BOT_ICON_SVG,
|
|
22
|
+
person: PERSON_ICON_SVG,
|
|
23
|
+
rovoHex: ROVO_HEX_ICON_SVG
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parsing the markup is the same work for every tag, so each icon is parsed once into a template
|
|
28
|
+
* and cloned per use — appending a `DocumentFragment` moves its children out of it, so a shared
|
|
29
|
+
* fragment would leave every icon after the first empty.
|
|
30
|
+
*/
|
|
31
|
+
const templates = {};
|
|
32
|
+
export const getContributorTagIcon = (icon, doc) => {
|
|
33
|
+
let template = templates[icon];
|
|
34
|
+
if (!template) {
|
|
35
|
+
template = doc.createElement('template');
|
|
36
|
+
template.innerHTML = markup[icon];
|
|
37
|
+
templates[icon] = template;
|
|
38
|
+
}
|
|
39
|
+
return template.content.cloneNode(true);
|
|
40
|
+
};
|
|
@@ -9,7 +9,6 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
9
9
|
import isEqual from 'lodash/isEqual';
|
|
10
10
|
import memoizeOne from 'memoize-one';
|
|
11
11
|
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
12
|
-
import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
|
|
13
12
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
14
13
|
import { Mapping } from '@atlaskit/editor-prosemirror/transform';
|
|
15
14
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
@@ -618,26 +617,21 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
|
|
|
618
617
|
if (change.isInline) {
|
|
619
618
|
// Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
|
|
620
619
|
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
621
|
-
var isAtomicInlineNodeFlag = isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
|
|
622
|
-
return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
|
|
623
|
-
});
|
|
624
620
|
decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration({
|
|
625
621
|
change: change,
|
|
626
622
|
colorScheme: colorScheme,
|
|
627
623
|
isActive: isActive,
|
|
628
624
|
isInserted: true,
|
|
629
|
-
isAtomicInlineNode:
|
|
625
|
+
isAtomicInlineNode: true,
|
|
630
626
|
inlineNodeName: change.inlineNodeName,
|
|
631
627
|
// Suppress the border-bottom underline for atomic inline nodeviews —
|
|
632
628
|
// it doesn't render on custom nodeview DOM elements and is unnecessary noise.
|
|
633
|
-
hideAddedDiffsUnderline:
|
|
629
|
+
hideAddedDiffsUnderline: true,
|
|
634
630
|
diffType: diffType
|
|
635
631
|
})));
|
|
636
632
|
// If we have the original node position, also render the old node as a "deleted" widget
|
|
637
633
|
// so the user can see what it looked like before the change.
|
|
638
|
-
if (change.fromA !== undefined && change.toA !== undefined
|
|
639
|
-
return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
|
|
640
|
-
})) {
|
|
634
|
+
if (change.fromA !== undefined && change.toA !== undefined) {
|
|
641
635
|
decorations.push.apply(decorations, _toConsumableArray(createNodeChangedDecorationWidget({
|
|
642
636
|
change: {
|
|
643
637
|
fromA: change.fromA,
|
|
@@ -212,7 +212,6 @@ var TEXT_BLOCK_TYPES = new Set(['paragraph', 'heading']);
|
|
|
212
212
|
* layoutColumn → layoutSection, tableCell/tableHeader → tableRow → table.
|
|
213
213
|
*/
|
|
214
214
|
var RIGID_CHILD_TYPES = new Set(['layoutColumn', 'tableCell', 'tableHeader']);
|
|
215
|
-
var TABLE_TYPE = 'table';
|
|
216
215
|
|
|
217
216
|
/**
|
|
218
217
|
* Emit a single whole-block (node-level) change covering both sides of a group. Used for
|
|
@@ -539,7 +538,7 @@ var classifyContainer = function classifyContainer(blockA, blockB, changes, orig
|
|
|
539
538
|
var typeName = blockB.node.type.name;
|
|
540
539
|
|
|
541
540
|
// Tables need cell-level counting across rows; handle them specially.
|
|
542
|
-
if (typeName ===
|
|
541
|
+
if (typeName === 'table') {
|
|
543
542
|
return classifyTable(blockA, blockB, changes, originalDoc, newDoc, locale, thresholds);
|
|
544
543
|
}
|
|
545
544
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _typeof from "@babel/runtime/helpers/typeof";
|
|
2
|
-
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
3
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
4
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
5
5
|
var _excluded = ["attribution", "connectedTo"];
|
|
6
6
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7
7
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -17,6 +17,19 @@ import { PARTICIPANT_COLOR_SCHEMES } from './types';
|
|
|
17
17
|
|
|
18
18
|
/** Contributors addressed by attribution key. The key format is internal. */
|
|
19
19
|
|
|
20
|
+
/** Maps the shared 18-slot telepointer palette onto the ten bolder diff colours. */
|
|
21
|
+
var HASHED_PARTICIPANT_COLOR_SCHEMES = [].concat(_toConsumableArray(PARTICIPANT_COLOR_SCHEMES), ['blue', 'red', 'orange', 'yellow', 'green', 'teal', 'purple', 'magenta']);
|
|
22
|
+
var getAvailableColor = function getAvailableColor(hashedColor, allocatedColors) {
|
|
23
|
+
var startIndex = PARTICIPANT_COLOR_SCHEMES.indexOf(hashedColor);
|
|
24
|
+
for (var offset = 0; offset < PARTICIPANT_COLOR_SCHEMES.length; offset++) {
|
|
25
|
+
var color = PARTICIPANT_COLOR_SCHEMES[(startIndex + offset) % PARTICIPANT_COLOR_SCHEMES.length];
|
|
26
|
+
if (color && !allocatedColors.has(color)) {
|
|
27
|
+
return color;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return hashedColor;
|
|
31
|
+
};
|
|
32
|
+
|
|
20
33
|
/**
|
|
21
34
|
* Normalise the attribution identity once so a valid lookup key always has a valid participant
|
|
22
35
|
* colour seed. `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared
|
|
@@ -112,6 +125,7 @@ export var isContributorTagsEnabled = function isContributorTagsEnabled(stepAttr
|
|
|
112
125
|
};
|
|
113
126
|
export var createAttributionColorMap = function createAttributionColorMap(stepAttributions) {
|
|
114
127
|
var colors = new Map();
|
|
128
|
+
var allocatedColors = new Set();
|
|
115
129
|
var _iterator2 = _createForOfIteratorHelper(stepAttributions),
|
|
116
130
|
_step2;
|
|
117
131
|
try {
|
|
@@ -123,10 +137,13 @@ export var createAttributionColorMap = function createAttributionColorMap(stepAt
|
|
|
123
137
|
}
|
|
124
138
|
var _getParticipantColor = getParticipantColor(identity.colorSeed),
|
|
125
139
|
index = _getParticipantColor.index;
|
|
126
|
-
var
|
|
127
|
-
if (
|
|
128
|
-
|
|
140
|
+
var hashedColor = HASHED_PARTICIPANT_COLOR_SCHEMES[index];
|
|
141
|
+
if (!hashedColor) {
|
|
142
|
+
continue;
|
|
129
143
|
}
|
|
144
|
+
var participantColorScheme = getAvailableColor(hashedColor, allocatedColors);
|
|
145
|
+
colors.set(identity.key, participantColorScheme);
|
|
146
|
+
allocatedColors.add(participantColorScheme);
|
|
130
147
|
}
|
|
131
148
|
} catch (err) {
|
|
132
149
|
_iterator2.e(err);
|
|
@@ -2,9 +2,6 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
4
|
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
5
|
-
import { participantColors } from '@atlaskit/editor-shared-styles/constants';
|
|
6
|
-
import { PARTICIPANT_COLOR_SCHEMES } from './types';
|
|
7
|
-
|
|
8
5
|
// token() is a build-time transform needing static literals, so pre-compute every colour's
|
|
9
6
|
// tokens here and index by name at runtime.
|
|
10
7
|
|
|
@@ -80,71 +77,23 @@ var textAccentMap = {
|
|
|
80
77
|
gray: "var(--ds-text-accent-gray, #505258)",
|
|
81
78
|
lime: "var(--ds-text-accent-lime, #4C6B1F)"
|
|
82
79
|
};
|
|
83
|
-
|
|
84
|
-
/** Pressed counterpart of each participant's diff-safe SVG background tint. */
|
|
85
|
-
var participantPressedBackgroundMap = {
|
|
86
|
-
'red-bolder': bgSubtlerPressedMap.red,
|
|
87
|
-
'blue-bolder': bgSubtlerPressedMap.blue,
|
|
88
|
-
'green-bolder': bgSubtlerPressedMap.green,
|
|
89
|
-
'yellow-bolder': bgSubtlerPressedMap.yellow,
|
|
90
|
-
'purple-bolder': bgSubtlerPressedMap.purple,
|
|
91
|
-
'magenta-bolder': bgSubtlerPressedMap.magenta,
|
|
92
|
-
'teal-bolder': bgSubtlerPressedMap.teal,
|
|
93
|
-
'orange-bolder': bgSubtlerPressedMap.orange,
|
|
94
|
-
'lime-bolder': bgSubtlerPressedMap.lime,
|
|
95
|
-
'gray-bolder': bgSubtlerPressedMap.gray,
|
|
96
|
-
'blue-subtle': bgSubtlestPressedMap.blue,
|
|
97
|
-
'red-subtle': bgSubtlestPressedMap.red,
|
|
98
|
-
'orange-subtle': bgSubtlestPressedMap.orange,
|
|
99
|
-
'yellow-subtle': bgSubtlestPressedMap.yellow,
|
|
100
|
-
'green-subtle': bgSubtlestPressedMap.green,
|
|
101
|
-
'teal-subtle': bgSubtlestPressedMap.teal,
|
|
102
|
-
'purple-subtle': bgSubtlestPressedMap.purple,
|
|
103
|
-
'magenta-subtle': bgSubtlestPressedMap.magenta
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* Telepointers can put inverse text directly on their bolder colour. Diff colours sit behind
|
|
107
|
-
* arbitrary document content, so use the participant SVG tint and its matching pressed token for
|
|
108
|
-
* diff backgrounds. Borders and rings use the exact participant colour, preserving all 18
|
|
109
|
-
* bolder/subtle slots while keeping every value in the shared ADS participant palette.
|
|
110
|
-
*/
|
|
111
|
-
var participantColorTokenSets = Object.fromEntries(PARTICIPANT_COLOR_SCHEMES.map(function (scheme, index) {
|
|
112
|
-
var participantColor = participantColors[index];
|
|
113
|
-
if (!participantColor) {
|
|
114
|
-
throw new Error("Missing shared participant colour for show-diff slot ".concat(index));
|
|
115
|
-
}
|
|
116
|
-
return [scheme, {
|
|
117
|
-
backgroundSubtlest: participantColor.svgBackgroundColor,
|
|
118
|
-
backgroundSubtlestPressed: participantPressedBackgroundMap[scheme],
|
|
119
|
-
backgroundSubtler: participantColor.svgBackgroundColor,
|
|
120
|
-
backgroundSubtlerPressed: participantPressedBackgroundMap[scheme],
|
|
121
|
-
borderAccent: participantColor.backgroundColor,
|
|
122
|
-
// The first ten bolder colours are safe as accents on the editor surface. The
|
|
123
|
-
// remaining subtle colours use their paired dark participant text colour.
|
|
124
|
-
textAccent: index < 10 ? participantColor.backgroundColor : participantColor.textColor
|
|
125
|
-
}];
|
|
126
|
-
}));
|
|
127
|
-
var participantColorSchemeSet = new Set(PARTICIPANT_COLOR_SCHEMES);
|
|
128
|
-
var isParticipantColorScheme = function isParticipantColorScheme(color) {
|
|
129
|
-
return participantColorSchemeSet.has(color);
|
|
130
|
-
};
|
|
131
80
|
function bgSubtlest(color) {
|
|
132
|
-
return
|
|
81
|
+
return bgSubtlestMap[color];
|
|
133
82
|
}
|
|
134
83
|
function bgSubtlestPressed(color) {
|
|
135
|
-
return
|
|
84
|
+
return bgSubtlestPressedMap[color];
|
|
136
85
|
}
|
|
137
86
|
function bgSubtler(color) {
|
|
138
|
-
return
|
|
87
|
+
return bgSubtlerMap[color];
|
|
139
88
|
}
|
|
140
89
|
function bgSubtlerPressed(color) {
|
|
141
|
-
return
|
|
90
|
+
return bgSubtlerPressedMap[color];
|
|
142
91
|
}
|
|
143
92
|
function borderAccent(color) {
|
|
144
|
-
return
|
|
93
|
+
return borderAccentMap[color];
|
|
145
94
|
}
|
|
146
95
|
function textAccent(color) {
|
|
147
|
-
return
|
|
96
|
+
return textAccentMap[color];
|
|
148
97
|
}
|
|
149
98
|
|
|
150
99
|
/** Presentation tokens for one diff colour, shared by highlights and contributor tags. */
|