@atlaskit/editor-plugin-mentions 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/.eslintrc.js +7 -0
  2. package/CHANGELOG.md +1 -0
  3. package/LICENSE.md +13 -0
  4. package/README.md +9 -0
  5. package/dist/cjs/analytics.js +157 -0
  6. package/dist/cjs/index.js +12 -0
  7. package/dist/cjs/messages.js +29 -0
  8. package/dist/cjs/nodeviews/mention.js +117 -0
  9. package/dist/cjs/plugin.js +135 -0
  10. package/dist/cjs/pm-plugins/key.js +8 -0
  11. package/dist/cjs/pm-plugins/main.js +156 -0
  12. package/dist/cjs/pm-plugins/utils.js +23 -0
  13. package/dist/cjs/type-ahead/index.js +362 -0
  14. package/dist/cjs/types.js +5 -0
  15. package/dist/cjs/ui/InviteItem/index.js +76 -0
  16. package/dist/cjs/ui/InviteItem/styles.js +19 -0
  17. package/dist/cjs/ui/Mention/index.js +98 -0
  18. package/dist/cjs/ui/ToolbarMention/index.js +63 -0
  19. package/dist/cjs/utils.js +32 -0
  20. package/dist/es2019/analytics.js +147 -0
  21. package/dist/es2019/index.js +1 -0
  22. package/dist/es2019/messages.js +23 -0
  23. package/dist/es2019/nodeviews/mention.js +80 -0
  24. package/dist/es2019/plugin.js +123 -0
  25. package/dist/es2019/pm-plugins/key.js +2 -0
  26. package/dist/es2019/pm-plugins/main.js +143 -0
  27. package/dist/es2019/pm-plugins/utils.js +14 -0
  28. package/dist/es2019/type-ahead/index.js +338 -0
  29. package/dist/es2019/types.js +1 -0
  30. package/dist/es2019/ui/InviteItem/index.js +67 -0
  31. package/dist/es2019/ui/InviteItem/styles.js +47 -0
  32. package/dist/es2019/ui/Mention/index.js +70 -0
  33. package/dist/es2019/ui/ToolbarMention/index.js +33 -0
  34. package/dist/es2019/utils.js +20 -0
  35. package/dist/esm/analytics.js +150 -0
  36. package/dist/esm/index.js +1 -0
  37. package/dist/esm/messages.js +23 -0
  38. package/dist/esm/nodeviews/mention.js +107 -0
  39. package/dist/esm/plugin.js +129 -0
  40. package/dist/esm/pm-plugins/key.js +2 -0
  41. package/dist/esm/pm-plugins/main.js +148 -0
  42. package/dist/esm/pm-plugins/utils.js +16 -0
  43. package/dist/esm/type-ahead/index.js +350 -0
  44. package/dist/esm/types.js +1 -0
  45. package/dist/esm/ui/InviteItem/index.js +66 -0
  46. package/dist/esm/ui/InviteItem/styles.js +12 -0
  47. package/dist/esm/ui/Mention/index.js +90 -0
  48. package/dist/esm/ui/ToolbarMention/index.js +53 -0
  49. package/dist/esm/utils.js +26 -0
  50. package/dist/types/analytics.d.ts +13 -0
  51. package/dist/types/index.d.ts +2 -0
  52. package/dist/types/messages.d.ts +22 -0
  53. package/dist/types/nodeviews/mention.d.ts +9 -0
  54. package/dist/types/plugin.d.ts +3 -0
  55. package/dist/types/pm-plugins/key.d.ts +3 -0
  56. package/dist/types/pm-plugins/main.d.ts +6 -0
  57. package/dist/types/pm-plugins/utils.d.ts +4 -0
  58. package/dist/types/type-ahead/index.d.ts +17 -0
  59. package/dist/types/types.d.ts +38 -0
  60. package/dist/types/ui/InviteItem/index.d.ts +24 -0
  61. package/dist/types/ui/InviteItem/styles.d.ts +8 -0
  62. package/dist/types/ui/Mention/index.d.ts +19 -0
  63. package/dist/types/ui/ToolbarMention/index.d.ts +13 -0
  64. package/dist/types/utils.d.ts +8 -0
  65. package/dist/types-ts4.5/analytics.d.ts +13 -0
  66. package/dist/types-ts4.5/index.d.ts +2 -0
  67. package/dist/types-ts4.5/messages.d.ts +22 -0
  68. package/dist/types-ts4.5/nodeviews/mention.d.ts +9 -0
  69. package/dist/types-ts4.5/plugin.d.ts +3 -0
  70. package/dist/types-ts4.5/pm-plugins/key.d.ts +3 -0
  71. package/dist/types-ts4.5/pm-plugins/main.d.ts +6 -0
  72. package/dist/types-ts4.5/pm-plugins/utils.d.ts +4 -0
  73. package/dist/types-ts4.5/type-ahead/index.d.ts +17 -0
  74. package/dist/types-ts4.5/types.d.ts +41 -0
  75. package/dist/types-ts4.5/ui/InviteItem/index.d.ts +24 -0
  76. package/dist/types-ts4.5/ui/InviteItem/styles.d.ts +8 -0
  77. package/dist/types-ts4.5/ui/Mention/index.d.ts +19 -0
  78. package/dist/types-ts4.5/ui/ToolbarMention/index.d.ts +13 -0
  79. package/dist/types-ts4.5/utils.d.ts +8 -0
  80. package/package.json +112 -0
  81. package/report.api.md +92 -0
  82. package/tmp/api-report-tmp.d.ts +63 -0
@@ -0,0 +1,350 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
4
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
5
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
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
+ 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; }
8
+ import React from 'react';
9
+ import uuid from 'uuid';
10
+ import { TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
11
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
12
+ import { MENTION_ITEM_HEIGHT, MentionItem } from '@atlaskit/mention/item';
13
+ import { isResolvingMentionProvider } from '@atlaskit/mention/resource';
14
+ import { buildTypeAheadCancelPayload, buildTypeAheadInsertedPayload, buildTypeAheadInviteExposurePayload, buildTypeAheadInviteItemClickedPayload, buildTypeAheadInviteItemViewedPayload, buildTypeAheadRenderedPayload } from '../analytics';
15
+ import { getMentionPluginState } from '../pm-plugins/utils';
16
+ import InviteItem, { INVITE_ITEM_DESCRIPTION } from '../ui/InviteItem';
17
+ import { isInviteItem, isTeamStats, isTeamType, shouldKeepInviteItem } from '../utils';
18
+ var createInviteItem = function createInviteItem(_ref) {
19
+ var mentionProvider = _ref.mentionProvider,
20
+ onInviteItemMount = _ref.onInviteItemMount;
21
+ return {
22
+ title: INVITE_ITEM_DESCRIPTION.id,
23
+ render: function render(_ref2) {
24
+ var isSelected = _ref2.isSelected,
25
+ onClick = _ref2.onClick,
26
+ onHover = _ref2.onHover;
27
+ return /*#__PURE__*/React.createElement(InviteItem, {
28
+ productName: mentionProvider ? mentionProvider.productName : undefined,
29
+ selected: isSelected,
30
+ onMount: onInviteItemMount,
31
+ onMouseEnter: onHover,
32
+ onSelection: onClick,
33
+ userRole: mentionProvider.userRole
34
+ });
35
+ },
36
+ mention: INVITE_ITEM_DESCRIPTION
37
+ };
38
+ };
39
+ var withInviteItem = function withInviteItem(_ref3) {
40
+ var mentionProvider = _ref3.mentionProvider,
41
+ firstQueryWithoutResults = _ref3.firstQueryWithoutResults,
42
+ currentQuery = _ref3.currentQuery,
43
+ onInviteItemMount = _ref3.onInviteItemMount;
44
+ return function (mentionItems) {
45
+ var inviteItem = createInviteItem({
46
+ mentionProvider: mentionProvider,
47
+ onInviteItemMount: onInviteItemMount
48
+ });
49
+ var keepInviteItem = shouldKeepInviteItem(currentQuery, firstQueryWithoutResults);
50
+ if (mentionItems.length === 0) {
51
+ return keepInviteItem ? [inviteItem] : [];
52
+ }
53
+ return [].concat(_toConsumableArray(mentionItems), [
54
+ // invite item should be shown at the bottom
55
+ inviteItem]);
56
+ };
57
+ };
58
+ export var mentionToTypeaheadItem = function mentionToTypeaheadItem(mention) {
59
+ return {
60
+ title: mention.id,
61
+ render: function render(_ref4) {
62
+ var isSelected = _ref4.isSelected,
63
+ onClick = _ref4.onClick,
64
+ onHover = _ref4.onHover;
65
+ return /*#__PURE__*/React.createElement(MentionItem, {
66
+ mention: mention,
67
+ selected: isSelected,
68
+ onMouseEnter: onHover,
69
+ onSelection: onClick
70
+ });
71
+ },
72
+ getCustomComponentHeight: function getCustomComponentHeight() {
73
+ return MENTION_ITEM_HEIGHT;
74
+ },
75
+ mention: mention
76
+ };
77
+ };
78
+ export function memoize(fn) {
79
+ // Cache results here
80
+ var seen = new Map();
81
+ function memoized(mention) {
82
+ // Check cache for hits
83
+ var hit = seen.get(mention.id);
84
+ if (hit) {
85
+ return hit;
86
+ }
87
+
88
+ // Generate new result and cache it
89
+ var result = fn(mention);
90
+ seen.set(mention.id, result);
91
+ return result;
92
+ }
93
+ return {
94
+ call: memoized,
95
+ clear: seen.clear.bind(seen)
96
+ };
97
+ }
98
+ var memoizedToItem = memoize(mentionToTypeaheadItem);
99
+ var buildAndSendElementsTypeAheadAnalytics = function buildAndSendElementsTypeAheadAnalytics(fireEvent) {
100
+ return function (_ref5) {
101
+ var query = _ref5.query,
102
+ mentions = _ref5.mentions,
103
+ stats = _ref5.stats;
104
+ var duration = 0;
105
+ var userOrTeamIds = null;
106
+ var teams = null;
107
+ if (!isTeamStats(stats)) {
108
+ // is from primary mention endpoint which could be just user mentions or user/team mentions
109
+ duration = stats && stats.duration;
110
+ teams = null;
111
+ userOrTeamIds = mentions.map(function (mention) {
112
+ return mention.id;
113
+ });
114
+ } else {
115
+ // is from dedicated team-only mention endpoint
116
+ duration = stats && stats.teamMentionDuration;
117
+ userOrTeamIds = null;
118
+ teams = mentions.map(function (mention) {
119
+ return isTeamType(mention.userType) ? {
120
+ teamId: mention.id,
121
+ includesYou: mention.context.includesYou,
122
+ memberCount: mention.context.memberCount
123
+ } : null;
124
+ }).filter(function (m) {
125
+ return !!m;
126
+ });
127
+ }
128
+ var payload = buildTypeAheadRenderedPayload(duration, userOrTeamIds, query, teams);
129
+ fireEvent(payload);
130
+ };
131
+ };
132
+
133
+ /**
134
+ * When a team mention is selected, we render a team link and list of member/user mentions
135
+ * in editor content
136
+ */
137
+ var buildNodesForTeamMention = function buildNodesForTeamMention(schema, selectedMention, mentionProvider, sanitizePrivateContent) {
138
+ var nodes = schema.nodes,
139
+ marks = schema.marks;
140
+ var name = selectedMention.name,
141
+ teamId = selectedMention.id,
142
+ accessLevel = selectedMention.accessLevel,
143
+ context = selectedMention.context;
144
+
145
+ // build team link
146
+ var defaultTeamLink = "".concat(window.location.origin, "/people/team/").concat(teamId);
147
+ var teamLink = context && context.teamLink ? context.teamLink : defaultTeamLink;
148
+ var teamLinkNode = schema.text(name, [marks.link.create({
149
+ href: teamLink
150
+ })]);
151
+ var openBracketText = schema.text('(');
152
+ var closeBracketText = schema.text(')');
153
+ var emptySpaceText = schema.text(' ');
154
+ var inlineNodes = [teamLinkNode, emptySpaceText, openBracketText];
155
+ var members = context && context.members ? context.members : [];
156
+ members.forEach(function (member, index) {
157
+ var name = member.name,
158
+ id = member.id;
159
+ var mentionName = "@".concat(name);
160
+ var text = sanitizePrivateContent ? '' : mentionName;
161
+ if (sanitizePrivateContent && isResolvingMentionProvider(mentionProvider)) {
162
+ mentionProvider.cacheMentionName(id, name);
163
+ }
164
+ var userMentionNode = nodes.mention.createChecked({
165
+ text: text,
166
+ id: member.id,
167
+ accessLevel: accessLevel,
168
+ userType: 'DEFAULT'
169
+ });
170
+ inlineNodes.push(userMentionNode);
171
+ // should not add empty space after the last user mention.
172
+ if (index !== members.length - 1) {
173
+ inlineNodes.push(emptySpaceText);
174
+ }
175
+ });
176
+ inlineNodes.push(closeBracketText);
177
+ return Fragment.fromArray(inlineNodes);
178
+ };
179
+ export var createTypeAheadConfig = function createTypeAheadConfig(_ref6) {
180
+ var sanitizePrivateContent = _ref6.sanitizePrivateContent,
181
+ mentionInsertDisplayName = _ref6.mentionInsertDisplayName,
182
+ fireEvent = _ref6.fireEvent,
183
+ HighlightComponent = _ref6.HighlightComponent;
184
+ var sessionId = uuid();
185
+ var firstQueryWithoutResults = null;
186
+ var subscriptionKeys = new Set();
187
+ var typeAhead = {
188
+ id: TypeAheadAvailableNodes.MENTION,
189
+ trigger: '@',
190
+ // Custom regex must have a capture group around trigger
191
+ // so it's possible to use it without needing to scan through all triggers again
192
+ customRegex: '\\(?(@)',
193
+ getHighlight: function getHighlight(state) {
194
+ var CustomHighlightComponent = HighlightComponent;
195
+ if (CustomHighlightComponent) {
196
+ return /*#__PURE__*/React.createElement(CustomHighlightComponent, null);
197
+ }
198
+ return null;
199
+ },
200
+ getItems: function getItems(_ref7) {
201
+ var query = _ref7.query,
202
+ editorState = _ref7.editorState;
203
+ var pluginState = getMentionPluginState(editorState);
204
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
205
+ return Promise.resolve([]);
206
+ }
207
+ var mentionProvider = pluginState.mentionProvider,
208
+ contextIdentifierProvider = pluginState.contextIdentifierProvider;
209
+ return new Promise(function (resolve) {
210
+ var key = "loadingMentionsForTypeAhead_".concat(uuid());
211
+ var mentionsSubscribeCallback = function mentionsSubscribeCallback(mentions) {
212
+ var resultQuery = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
213
+ var stats = arguments.length > 2 ? arguments[2] : undefined;
214
+ if (query !== resultQuery) {
215
+ return;
216
+ }
217
+ mentionProvider.unsubscribe(key);
218
+ subscriptionKeys.delete(key);
219
+ var mentionItems = mentions.map(function (mention) {
220
+ return memoizedToItem.call(mention);
221
+ });
222
+ buildAndSendElementsTypeAheadAnalytics(fireEvent)({
223
+ query: query,
224
+ mentions: mentions,
225
+ stats: stats
226
+ });
227
+ if (mentions.length === 0 && firstQueryWithoutResults === null) {
228
+ firstQueryWithoutResults = query;
229
+ }
230
+
231
+ // Growth (El-dorado) experiment design hard requirement
232
+ if (mentionItems.length <= 2) {
233
+ var inviteExperimentCohort = mentionProvider.inviteExperimentCohort,
234
+ userRole = mentionProvider.userRole;
235
+ fireEvent(buildTypeAheadInviteExposurePayload(sessionId, contextIdentifierProvider, inviteExperimentCohort, userRole));
236
+ }
237
+ if (!mentionProvider.shouldEnableInvite || mentionItems.length > 2) {
238
+ resolve(mentionItems);
239
+ } else {
240
+ var items = withInviteItem({
241
+ mentionProvider: mentionProvider,
242
+ firstQueryWithoutResults: firstQueryWithoutResults || '',
243
+ currentQuery: query,
244
+ onInviteItemMount: function onInviteItemMount() {
245
+ fireEvent(buildTypeAheadInviteItemViewedPayload(sessionId, contextIdentifierProvider, mentionProvider.userRole));
246
+ }
247
+ })(mentionItems);
248
+ resolve(items);
249
+ }
250
+ };
251
+ subscriptionKeys.add(key);
252
+ mentionProvider.subscribe(key, mentionsSubscribeCallback);
253
+ mentionProvider.filter(query || '', _objectSpread(_objectSpread({}, contextIdentifierProvider), {}, {
254
+ sessionId: sessionId
255
+ }));
256
+ });
257
+ },
258
+ onOpen: function onOpen() {
259
+ firstQueryWithoutResults = null;
260
+ },
261
+ selectItem: function selectItem(state, item, insert, _ref8) {
262
+ var mode = _ref8.mode,
263
+ stats = _ref8.stats,
264
+ query = _ref8.query,
265
+ sourceListItem = _ref8.sourceListItem;
266
+ var schema = state.schema;
267
+ var pluginState = getMentionPluginState(state);
268
+ var mentionProvider = pluginState.mentionProvider;
269
+ var _item$mention = item.mention,
270
+ id = _item$mention.id,
271
+ name = _item$mention.name,
272
+ nickname = _item$mention.nickname,
273
+ accessLevel = _item$mention.accessLevel,
274
+ userType = _item$mention.userType;
275
+ var trimmedNickname = nickname && nickname.startsWith('@') ? nickname.slice(1) : nickname;
276
+ var renderName = mentionInsertDisplayName || !trimmedNickname ? name : trimmedNickname;
277
+ var mentionContext = _objectSpread(_objectSpread({}, pluginState.contextIdentifierProvider), {}, {
278
+ sessionId: sessionId
279
+ });
280
+ if (mentionProvider && !isInviteItem(item.mention)) {
281
+ mentionProvider.recordMentionSelection(item.mention, mentionContext);
282
+ }
283
+
284
+ // use same timer as StatsModifier
285
+ var pickerElapsedTime = stats.startedAt ? performance.now() - stats.startedAt : 0;
286
+ if (mentionProvider && mentionProvider.shouldEnableInvite && isInviteItem(item.mention)) {
287
+ // Don't fire event and the callback with selection by space press
288
+ if (mode !== 'space') {
289
+ fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, pluginState.contextIdentifierProvider, mentionProvider.userRole));
290
+ if (mentionProvider.onInviteItemClick) {
291
+ mentionProvider.onInviteItemClick('mention');
292
+ }
293
+ }
294
+ return state.tr;
295
+ }
296
+ fireEvent(buildTypeAheadInsertedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, item.mention, sourceListItem.map(function (x) {
297
+ return x.mention;
298
+ }), query, pluginState.contextIdentifierProvider));
299
+ sessionId = uuid();
300
+ if (mentionProvider && isTeamType(userType)) {
301
+ return insert(buildNodesForTeamMention(schema, item.mention, mentionProvider, sanitizePrivateContent));
302
+ }
303
+
304
+ // Don't insert into document if document data is sanitized.
305
+ var text = sanitizePrivateContent ? '' : "@".concat(renderName);
306
+ if (sanitizePrivateContent && isResolvingMentionProvider(mentionProvider)) {
307
+ // Cache (locally) for later rendering
308
+ mentionProvider.cacheMentionName(id, renderName);
309
+ }
310
+ var mentionNode = schema.nodes.mention.createChecked({
311
+ text: text,
312
+ id: id,
313
+ accessLevel: accessLevel,
314
+ userType: userType === 'DEFAULT' ? null : userType
315
+ });
316
+ var space = schema.text(' ');
317
+ return insert(Fragment.from([mentionNode, space]));
318
+ },
319
+ dismiss: function dismiss(_ref9) {
320
+ var editorState = _ref9.editorState,
321
+ query = _ref9.query,
322
+ stats = _ref9.stats,
323
+ wasItemInserted = _ref9.wasItemInserted;
324
+ firstQueryWithoutResults = null;
325
+ var pickerElapsedTime = stats.startedAt ? performance.now() - stats.startedAt : 0;
326
+ if (!wasItemInserted) {
327
+ fireEvent(buildTypeAheadCancelPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, query || ''));
328
+ }
329
+ var pluginState = getMentionPluginState(editorState);
330
+ if (pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider) {
331
+ var mentionProvider = pluginState.mentionProvider;
332
+ var _iterator = _createForOfIteratorHelper(subscriptionKeys),
333
+ _step;
334
+ try {
335
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
336
+ var key = _step.value;
337
+ mentionProvider.unsubscribe(key);
338
+ }
339
+ } catch (err) {
340
+ _iterator.e(err);
341
+ } finally {
342
+ _iterator.f();
343
+ }
344
+ }
345
+ subscriptionKeys.clear();
346
+ sessionId = uuid();
347
+ }
348
+ };
349
+ return typeAhead;
350
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ /** @jsx jsx */
3
+
4
+ import React, { useCallback, useEffect } from 'react';
5
+ import { jsx } from '@emotion/react';
6
+ import { FormattedMessage, injectIntl } from 'react-intl-next';
7
+ import AddIcon from '@atlaskit/icon/glyph/add';
8
+ import { N300 } from '@atlaskit/theme/colors';
9
+ import { messages } from '../../messages';
10
+ import { avatarStyle, capitalizedStyle, mentionItemSelectedStyle, mentionItemStyle, nameSectionStyle, rowStyle } from './styles';
11
+ export var INVITE_ITEM_DESCRIPTION = {
12
+ id: 'invite-teammate'
13
+ };
14
+ var leftClick = function leftClick(event) {
15
+ return event.button === 0 && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey;
16
+ };
17
+ var InviteItem = function InviteItem(_ref) {
18
+ var productName = _ref.productName,
19
+ onMount = _ref.onMount,
20
+ onMouseEnter = _ref.onMouseEnter,
21
+ onSelection = _ref.onSelection,
22
+ selected = _ref.selected,
23
+ userRole = _ref.userRole,
24
+ intl = _ref.intl;
25
+ var onSelected = useCallback(function (event) {
26
+ if (leftClick(event) && onSelection) {
27
+ event.preventDefault();
28
+ onSelection(INVITE_ITEM_DESCRIPTION, event);
29
+ }
30
+ }, [onSelection]);
31
+ var onItemMouseEnter = useCallback(function (event) {
32
+ if (onMouseEnter) {
33
+ onMouseEnter(INVITE_ITEM_DESCRIPTION, event);
34
+ }
35
+ }, [onMouseEnter]);
36
+ useEffect(function () {
37
+ if (onMount) {
38
+ onMount();
39
+ }
40
+ }, [onMount]);
41
+ return jsx("div", {
42
+ css: [mentionItemStyle, selected && mentionItemSelectedStyle],
43
+ onMouseDown: onSelected,
44
+ onMouseEnter: onItemMouseEnter,
45
+ "data-id": INVITE_ITEM_DESCRIPTION.id
46
+ }, jsx("div", {
47
+ css: rowStyle
48
+ }, jsx("span", {
49
+ css: avatarStyle
50
+ }, jsx(AddIcon, {
51
+ label: intl.formatMessage(messages.mentionsAddLabel),
52
+ primaryColor: "var(--ds-icon-subtle, ".concat(N300, ")")
53
+ })), jsx("div", {
54
+ css: nameSectionStyle,
55
+ "data-testid": "name-section"
56
+ }, jsx(FormattedMessage, _extends({}, messages.inviteItemTitle, {
57
+ values: {
58
+ userRole: userRole || 'basic',
59
+ productName: jsx("span", {
60
+ css: capitalizedStyle,
61
+ "data-testid": "capitalized-message"
62
+ }, productName)
63
+ }
64
+ })))));
65
+ };
66
+ export default injectIntl(InviteItem);
@@ -0,0 +1,12 @@
1
+ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6;
3
+ import { css } from '@emotion/react';
4
+ import { N30, N300 } from '@atlaskit/theme/colors';
5
+ export var ROW_SIDE_PADDING = 14;
6
+ export var rowStyle = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n align-items: center;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n overflow: hidden;\n padding: ", " ", "px;\n text-overflow: ellipsis;\n vertical-align: middle;\n"])), "var(--ds-space-075, 6px)", ROW_SIDE_PADDING);
7
+ export var AVATAR_HEIGHT = 36;
8
+ export var avatarStyle = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: relative;\n flex: initial;\n opacity: inherit;\n width: 36px;\n height: ", "px;\n\n > span {\n width: 24px;\n height: 24px;\n padding: ", ";\n }\n"])), AVATAR_HEIGHT, "var(--ds-space-075, 6px)");
9
+ export var nameSectionStyle = css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n flex: 1;\n min-width: 0;\n margin-left: 14px;\n color: ", ";\n opacity: inherit;\n"])), "var(--ds-text-subtle, ".concat(N300, ")"));
10
+ export var mentionItemStyle = css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n background-color: transparent;\n display: block;\n overflow: hidden;\n list-style-type: none;\n cursor: pointer;\n"])));
11
+ export var mentionItemSelectedStyle = css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n background-color: ", ";\n"])), "var(--ds-background-neutral-subtle-hovered, ".concat(N30, ")"));
12
+ export var capitalizedStyle = css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n text-transform: capitalize;\n"])));
@@ -0,0 +1,90 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
+ import _createClass from "@babel/runtime/helpers/createClass";
4
+ import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
5
+ import _inherits from "@babel/runtime/helpers/inherits";
6
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
7
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
8
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
9
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
10
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
11
+ import React from 'react';
12
+ import { PureComponent } from 'react';
13
+ import { ProviderFactory, WithProviders } from '@atlaskit/editor-common/provider-factory';
14
+ import { browser } from '@atlaskit/editor-common/utils';
15
+ import { ResourcedMention } from '@atlaskit/mention/element';
16
+ // Workaround for a firefox issue where dom selection is off sync
17
+ // https://product-fabric.atlassian.net/browse/ED-12442
18
+ var refreshBrowserSelection = function refreshBrowserSelection() {
19
+ var domSelection = window.getSelection();
20
+ if (domSelection) {
21
+ var domRange = domSelection && domSelection.rangeCount === 1 && domSelection.getRangeAt(0).cloneRange();
22
+ if (domRange) {
23
+ domSelection.removeAllRanges();
24
+ domSelection.addRange(domRange);
25
+ }
26
+ }
27
+ };
28
+ var Mention = /*#__PURE__*/function (_PureComponent) {
29
+ _inherits(Mention, _PureComponent);
30
+ var _super = _createSuper(Mention);
31
+ function Mention(props) {
32
+ var _this;
33
+ _classCallCheck(this, Mention);
34
+ _this = _super.call(this, props);
35
+ _defineProperty(_assertThisInitialized(_this), "renderWithProvider", function (providers) {
36
+ var _this$props = _this.props,
37
+ accessLevel = _this$props.accessLevel,
38
+ eventHandlers = _this$props.eventHandlers,
39
+ id = _this$props.id,
40
+ text = _this$props.text;
41
+ var _ref = providers,
42
+ mentionProvider = _ref.mentionProvider;
43
+ var actionHandlers = {};
44
+ ['onClick', 'onMouseEnter', 'onMouseLeave'].forEach(function (handler) {
45
+ actionHandlers[handler] = eventHandlers && eventHandlers[handler] || function () {};
46
+ });
47
+ return /*#__PURE__*/React.createElement(ResourcedMention, _extends({
48
+ id: id,
49
+ text: text,
50
+ accessLevel: accessLevel,
51
+ mentionProvider: mentionProvider
52
+ }, actionHandlers));
53
+ });
54
+ _this.providerFactory = props.providers || new ProviderFactory();
55
+ return _this;
56
+ }
57
+ _createClass(Mention, [{
58
+ key: "componentDidMount",
59
+ value: function componentDidMount() {
60
+ // Workaround an issue where the selection is not updated immediately after adding
61
+ // a mention when "sanitizePrivateContent" is enabled in the editor on safari.
62
+ // This affects both insertion and paste behaviour it is applied to the component.
63
+ // https://product-fabric.atlassian.net/browse/ED-14859
64
+ if (browser.safari) {
65
+ setTimeout(refreshBrowserSelection, 0);
66
+ }
67
+ }
68
+ }, {
69
+ key: "componentWillUnmount",
70
+ value: function componentWillUnmount() {
71
+ if (!this.props.providers) {
72
+ // new ProviderFactory is created if no `providers` has been set
73
+ // in this case when component is unmounted it's safe to destroy this providerFactory
74
+ this.providerFactory.destroy();
75
+ }
76
+ }
77
+ }, {
78
+ key: "render",
79
+ value: function render() {
80
+ return /*#__PURE__*/React.createElement(WithProviders, {
81
+ providers: ['mentionProvider', 'profilecardProvider'],
82
+ providerFactory: this.providerFactory,
83
+ renderNode: this.renderWithProvider
84
+ });
85
+ }
86
+ }]);
87
+ return Mention;
88
+ }(PureComponent);
89
+ _defineProperty(Mention, "displayName", 'Mention');
90
+ export { Mention as default };
@@ -0,0 +1,53 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
4
+ import _inherits from "@babel/runtime/helpers/inherits";
5
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
6
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
7
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
8
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
9
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
10
+ import React, { PureComponent } from 'react';
11
+ import { injectIntl } from 'react-intl-next';
12
+ import { TOOLBAR_BUTTON, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
13
+ import MentionIcon from '@atlaskit/icon/glyph/editor/mention';
14
+ import { messages } from '../../messages';
15
+ var ToolbarMention = /*#__PURE__*/function (_PureComponent) {
16
+ _inherits(ToolbarMention, _PureComponent);
17
+ var _super = _createSuper(ToolbarMention);
18
+ function ToolbarMention() {
19
+ var _this;
20
+ _classCallCheck(this, ToolbarMention);
21
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
22
+ args[_key] = arguments[_key];
23
+ }
24
+ _this = _super.call.apply(_super, [this].concat(args));
25
+ _defineProperty(_assertThisInitialized(_this), "handleInsertMention", function () {
26
+ if (!_this.props.editorView) {
27
+ return false;
28
+ }
29
+ _this.props.onInsertMention();
30
+ return true;
31
+ });
32
+ return _this;
33
+ }
34
+ _createClass(ToolbarMention, [{
35
+ key: "render",
36
+ value: function render() {
37
+ var mentionStringTranslated = this.props.intl.formatMessage(messages.mentionsIconLabel);
38
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
39
+ testId: this.props.testId,
40
+ buttonId: TOOLBAR_BUTTON.MENTION,
41
+ spacing: "none",
42
+ onClick: this.handleInsertMention,
43
+ disabled: this.props.isDisabled,
44
+ title: mentionStringTranslated + '@',
45
+ iconBefore: /*#__PURE__*/React.createElement(MentionIcon, {
46
+ label: mentionStringTranslated
47
+ })
48
+ });
49
+ }
50
+ }]);
51
+ return ToolbarMention;
52
+ }(PureComponent);
53
+ export default injectIntl(ToolbarMention);
@@ -0,0 +1,26 @@
1
+ import { INVITE_ITEM_DESCRIPTION } from './ui/InviteItem';
2
+ export var isTeamType = function isTeamType(userType) {
3
+ return userType === 'TEAM';
4
+ };
5
+ export var isTeamStats = function isTeamStats(stat) {
6
+ return stat && !isNaN(stat.teamMentionDuration);
7
+ };
8
+ export var isInviteItem = function isInviteItem(mention) {
9
+ return mention && mention.id === INVITE_ITEM_DESCRIPTION.id;
10
+ };
11
+
12
+ /**
13
+ * Actions
14
+ */
15
+ export var shouldKeepInviteItem = function shouldKeepInviteItem(query, firstQueryWithoutResults) {
16
+ if (!firstQueryWithoutResults) {
17
+ return true;
18
+ }
19
+ var lastIndexWithResults = firstQueryWithoutResults.length - 1;
20
+ var suffix = query.slice(lastIndexWithResults);
21
+ if (query[lastIndexWithResults - 1] === ' ') {
22
+ suffix = ' ' + suffix;
23
+ }
24
+ var depletedExtraWords = /\s[^\s]+\s/.test(suffix);
25
+ return !depletedExtraWords;
26
+ };
@@ -0,0 +1,13 @@
1
+ import type { EventType, GasPayload } from '@atlaskit/analytics-gas-types';
2
+ import type { ContextIdentifierProvider } from '@atlaskit/editor-common/provider-factory';
3
+ import type { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
4
+ import type { InviteExperimentCohort, UserRole } from '@atlaskit/mention';
5
+ import type { MentionDescription } from '@atlaskit/mention/resource';
6
+ import type { TeamInfoAttrAnalytics } from './types';
7
+ export declare const buildAnalyticsPayload: (actionSubject: string, action: string, eventType: EventType, sessionId: string, otherAttributes?: {}, tags?: Array<string>) => GasPayload;
8
+ export declare const buildTypeAheadCancelPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, query?: string) => GasPayload;
9
+ export declare const buildTypeAheadInviteItemViewedPayload: (sessionId: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole) => GasPayload;
10
+ export declare const buildTypeAheadInviteExposurePayload: (sessionId: string, contextIdentifierProvider?: ContextIdentifierProvider, inviteExperimentCohort?: InviteExperimentCohort, userRole?: UserRole) => GasPayload;
11
+ export declare const buildTypeAheadInviteItemClickedPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, insertType: SelectItemMode, query?: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole) => GasPayload;
12
+ export declare const buildTypeAheadInsertedPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, insertType: SelectItemMode, mention: MentionDescription, mentionList?: MentionDescription[], query?: string, contextIdentifierProvider?: ContextIdentifierProvider) => GasPayload;
13
+ export declare const buildTypeAheadRenderedPayload: (duration: number, userIds: Array<string> | null, query: string, teams: TeamInfoAttrAnalytics[] | null) => GasPayload;
@@ -0,0 +1,2 @@
1
+ export { mentionsPlugin } from './plugin';
2
+ export type { MentionPluginConfig, MentionsPlugin } from './types';
@@ -0,0 +1,22 @@
1
+ export declare const messages: {
2
+ inviteItemTitle: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ mentionsAddLabel: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ mentionsIconLabel: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ mentionsNodeLabel: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
3
+ import type { InlineNodeViewComponentProps } from '@atlaskit/editor-common/react-node-view';
4
+ import type { MentionPluginOptions } from '../types';
5
+ export type Props = InlineNodeViewComponentProps & {
6
+ options: MentionPluginOptions | undefined;
7
+ providerFactory: ProviderFactory;
8
+ };
9
+ export declare const MentionNodeView: React.FC<Props>;
@@ -0,0 +1,3 @@
1
+ import type { MentionsPlugin } from './types';
2
+ declare const mentionsPlugin: MentionsPlugin;
3
+ export { mentionsPlugin };
@@ -0,0 +1,3 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ import type { MentionPluginState } from '../types';
3
+ export declare const mentionPluginKey: PluginKey<MentionPluginState>;