@atlaskit/editor-plugin-mentions 17.1.5 → 17.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/editor-plugin-mentions
2
2
 
3
+ ## 17.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 17.1.6
10
+
11
+ ### Patch Changes
12
+
13
+ - [`73f8a70eba228`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/73f8a70eba228) -
14
+ [ux] Behind platform_editor_mention_search_order, identify agents during mention search and move
15
+ them above bots and teams without adding a new typeahead section.
16
+
3
17
  ## 17.1.5
4
18
 
5
19
  ### Patch Changes
@@ -67,7 +67,7 @@ var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
67
67
  var AGENT_MENTION_INACTIVITY_MS = 3000;
68
68
  var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
69
69
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
70
- var PACKAGE_VERSION = "17.1.4";
70
+ var PACKAGE_VERSION = "17.1.6";
71
71
  var setProvider = function setProvider(provider) {
72
72
  return function (state, dispatch) {
73
73
  if (dispatch) {
@@ -41,6 +41,15 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
41
41
  var isAgentTypeAheadItem = function isAgentTypeAheadItem(item) {
42
42
  return item.mention ? (0, _utils3.isAgentMention)(item.mention) : false;
43
43
  };
44
+ var isSearchOrderedAgentTypeAheadItem = function isSearchOrderedAgentTypeAheadItem(item) {
45
+ return !!item.mention && (0, _utils3.isExplicitAgentMention)(item.mention);
46
+ };
47
+ var isSearchOrderedPersonTypeAheadItem = function isSearchOrderedPersonTypeAheadItem(item) {
48
+ return !!item.mention && !(0, _utils3.isInviteItem)(item.mention) && !(0, _utils3.isExplicitAgentMention)(item.mention) && !(0, _utils3.isBotOrTeamMention)(item.mention);
49
+ };
50
+ var shouldApplyMentionSearchOrder = function shouldApplyMentionSearchOrder(query) {
51
+ return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_mention_search_order') && query.trim().length > 0;
52
+ };
44
53
 
45
54
  // A non-selectable loading placeholder injected by the provider (e.g.
46
55
  // `RovoChatMentionResource`) while the slower agent source resolves. It
@@ -288,13 +297,14 @@ var makeTransformMentionsToTypeAheadItems = function makeTransformMentionsToType
288
297
  mentionProvider = _ref8.mentionProvider,
289
298
  contextIdentifierProvider = _ref8.contextIdentifierProvider,
290
299
  sessionId = _ref8.sessionId;
291
- var mentionItems = mentions.map(function (mention) {
300
+ var displayMentions = shouldApplyMentionSearchOrder(query) ? (0, _utils3.orderMentionsForDisplay)(mentions) : mentions;
301
+ var mentionItems = displayMentions.map(function (mention) {
292
302
  return toItem(mention);
293
303
  });
294
304
  // The loading placeholder is a rendered-only row — keep it in
295
305
  // `mentionItems` so the shimmer shows, but exclude it from analytics
296
306
  // and no-results bookkeeping so it isn't counted as a real result.
297
- var realMentions = mentions.filter(function (mention) {
307
+ var realMentions = displayMentions.filter(function (mention) {
298
308
  return !isLoadingPlaceholder(mention);
299
309
  });
300
310
  var agentCount = realMentions.filter(_utils3.isAgentMention).length;
@@ -349,6 +359,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
349
359
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
350
360
  var sessionId = (0, _uuid.default)();
351
361
  var firstQueryWithoutResults = null;
362
+ var lastTypeAheadQuery = '';
352
363
  var subscriptionKeys = new Set();
353
364
  var transformMentionsToTypeAheadItems = makeTransformMentionsToTypeAheadItems({
354
365
  enableAgentSectioning: enableAgentSectioning,
@@ -381,6 +392,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
381
392
  var _api$contextIdentifie, _api$contextIdentifie2;
382
393
  var query = _ref0.query,
383
394
  editorState = _ref0.editorState;
395
+ lastTypeAheadQuery = query || '';
384
396
  var pluginState = (0, _utils2.getMentionPluginState)(editorState);
385
397
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
386
398
  return Promise.resolve([]);
@@ -427,10 +439,11 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
427
439
  if (!enableAgentSectioning) {
428
440
  return [];
429
441
  }
442
+ var applySearchOrder = shouldApplyMentionSearchOrder(lastTypeAheadQuery);
430
443
  return [{
431
444
  id: 'people',
432
445
  title: intl.formatMessage(_messages.mentionMessages.typeAheadSectionPeople),
433
- filter: function filter(item) {
446
+ filter: applySearchOrder ? isSearchOrderedPersonTypeAheadItem : function (item) {
434
447
  if (isAgentTypeAheadItem(item)) {
435
448
  return false;
436
449
  }
@@ -451,9 +464,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
451
464
  }, {
452
465
  id: 'agents',
453
466
  title: intl.formatMessage(_messages.mentionMessages.typeAheadSectionAgents),
454
- filter: function filter(item) {
455
- return isAgentTypeAheadItem(item);
456
- },
467
+ filter: applySearchOrder ? isSearchOrderedAgentTypeAheadItem : isAgentTypeAheadItem,
457
468
  limit: 5,
458
469
  sectionTitleDisplay: {
459
470
  showWhenQueryPresent: false,
@@ -466,6 +477,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
466
477
  },
467
478
  onOpen: function onOpen() {
468
479
  firstQueryWithoutResults = null;
480
+ lastTypeAheadQuery = '';
469
481
  },
470
482
  selectItem: function selectItem(state, item, insert, _ref11) {
471
483
  var _api$contextIdentifie3, _api$contextIdentifie4;
@@ -669,6 +681,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
669
681
  var _api$contextIdentifie5, _api$contextIdentifie6;
670
682
  var query = _ref14.query,
671
683
  editorState = _ref14.editorState;
684
+ lastTypeAheadQuery = query || '';
672
685
  var pluginState = (0, _utils2.getMentionPluginState)(editorState);
673
686
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
674
687
  return {
@@ -3,8 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.shouldKeepInviteItem = exports.isTeamType = exports.isTeamStats = exports.isInviteItem = exports.isAgentUserType = exports.isAgentMention = void 0;
6
+ exports.shouldKeepInviteItem = exports.orderMentionsForDisplay = exports.isTeamType = exports.isTeamStats = exports.isInviteItem = exports.isExplicitAgentMention = exports.isBotOrTeamMention = exports.isAgentUserType = exports.isAgentMention = exports.getMentionDisplayGroup = void 0;
7
7
  var _InviteItem = require("../InviteItem");
8
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
9
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
8
11
  // Ignored via go/ees005
9
12
  // eslint-disable-next-line require-unicode-regexp
10
13
  var SUFFIX_WITH_EXTRA_WORDS_REGEX = /\s[^\s]+\s/;
@@ -30,6 +33,66 @@ var isAgentMention = exports.isAgentMention = function isAgentMention(mention) {
30
33
  return isAgentUserType(mention.userType) || mention.appType === 'agent';
31
34
  };
32
35
 
36
+ /**
37
+ * True when the mention is explicitly an agent, not a generic APP/bot.
38
+ * Prefer this over {@link isAgentMention} when ordering the search display
39
+ * list behind `platform_editor_mention_search_order` — bare `userType: 'APP'`
40
+ * is a bot unless `appType === 'agent'`.
41
+ */
42
+ var isExplicitAgentMention = exports.isExplicitAgentMention = function isExplicitAgentMention(mention) {
43
+ return mention.appType === 'agent' || mention.userType === 'AGENT';
44
+ };
45
+
46
+ /**
47
+ * Connect/app bots and teams. Explicit agents are excluded so they can be
48
+ * lifted above this group in the hardcoded display order.
49
+ */
50
+ var isBotOrTeamMention = exports.isBotOrTeamMention = function isBotOrTeamMention(mention) {
51
+ if (isExplicitAgentMention(mention)) {
52
+ return false;
53
+ }
54
+ return mention.userType === 'TEAM' || mention.userType === 'APP';
55
+ };
56
+ var getMentionDisplayGroup = exports.getMentionDisplayGroup = function getMentionDisplayGroup(mention) {
57
+ if (isExplicitAgentMention(mention)) {
58
+ return 'agents';
59
+ }
60
+ if (isBotOrTeamMention(mention)) {
61
+ return 'bots-teams';
62
+ }
63
+ return 'people';
64
+ };
65
+
66
+ /**
67
+ * Hardcoded mention display order: people, then agents, then bots/teams.
68
+ * Stable within each group so provider ranking is preserved.
69
+ */
70
+ var orderMentionsForDisplay = exports.orderMentionsForDisplay = function orderMentionsForDisplay(mentions) {
71
+ var people = [];
72
+ var agents = [];
73
+ var botsAndTeams = [];
74
+ var _iterator = _createForOfIteratorHelper(mentions),
75
+ _step;
76
+ try {
77
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
78
+ var mention = _step.value;
79
+ var group = getMentionDisplayGroup(mention);
80
+ if (group === 'agents') {
81
+ agents.push(mention);
82
+ } else if (group === 'bots-teams') {
83
+ botsAndTeams.push(mention);
84
+ } else {
85
+ people.push(mention);
86
+ }
87
+ }
88
+ } catch (err) {
89
+ _iterator.e(err);
90
+ } finally {
91
+ _iterator.f();
92
+ }
93
+ return [].concat(people, agents, botsAndTeams);
94
+ };
95
+
33
96
  /**
34
97
  * Actions
35
98
  */
@@ -51,7 +51,7 @@ const AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
51
51
  const AGENT_MENTION_INACTIVITY_MS = 3000;
52
52
  const MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
53
53
  const PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
54
- const PACKAGE_VERSION = "17.1.4";
54
+ const PACKAGE_VERSION = "17.1.6";
55
55
  const setProvider = provider => (state, dispatch) => {
56
56
  if (dispatch) {
57
57
  dispatch(state.tr.setMeta(mentionPluginKey, {
@@ -21,8 +21,11 @@ import InviteItem, { INVITE_ITEM_DESCRIPTION } from '../InviteItem';
21
21
  import InviteItemWithEmailDomain from '../InviteItem/InviteItemWithEmailDomain';
22
22
  import { buildTypeAheadCancelPayload, buildTypeAheadInsertedPayload, buildTypeAheadInviteItemClickedPayload, buildTypeAheadInviteItemViewedPayload, buildTypeAheadRenderedPayload } from './analytics';
23
23
  import { MentionItemWithProfileCard } from './MentionItemWithProfileCard';
24
- import { isAgentMention, isInviteItem, isTeamStats, isTeamType, shouldKeepInviteItem } from './utils';
24
+ import { isAgentMention, isBotOrTeamMention, isExplicitAgentMention, isInviteItem, isTeamStats, isTeamType, orderMentionsForDisplay, shouldKeepInviteItem } from './utils';
25
25
  const isAgentTypeAheadItem = item => item.mention ? isAgentMention(item.mention) : false;
26
+ const isSearchOrderedAgentTypeAheadItem = item => !!item.mention && isExplicitAgentMention(item.mention);
27
+ const isSearchOrderedPersonTypeAheadItem = item => !!item.mention && !isInviteItem(item.mention) && !isExplicitAgentMention(item.mention) && !isBotOrTeamMention(item.mention);
28
+ const shouldApplyMentionSearchOrder = query => isExperimentEnabled('platform_editor_mention_search_order') && query.trim().length > 0;
26
29
 
27
30
  // A non-selectable loading placeholder injected by the provider (e.g.
28
31
  // `RovoChatMentionResource`) while the slower agent source resolves. It
@@ -262,11 +265,12 @@ const makeTransformMentionsToTypeAheadItems = ({
262
265
  contextIdentifierProvider,
263
266
  sessionId
264
267
  }) => {
265
- const mentionItems = mentions.map(mention => toItem(mention));
268
+ const displayMentions = shouldApplyMentionSearchOrder(query) ? orderMentionsForDisplay(mentions) : mentions;
269
+ const mentionItems = displayMentions.map(mention => toItem(mention));
266
270
  // The loading placeholder is a rendered-only row — keep it in
267
271
  // `mentionItems` so the shimmer shows, but exclude it from analytics
268
272
  // and no-results bookkeeping so it isn't counted as a real result.
269
- const realMentions = mentions.filter(mention => !isLoadingPlaceholder(mention));
273
+ const realMentions = displayMentions.filter(mention => !isLoadingPlaceholder(mention));
270
274
  const agentCount = realMentions.filter(isAgentMention).length;
271
275
  const agentAnalytics = {
272
276
  agentCount,
@@ -318,6 +322,7 @@ export const createTypeAheadConfig = ({
318
322
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
319
323
  let sessionId = uuid();
320
324
  let firstQueryWithoutResults = null;
325
+ let lastTypeAheadQuery = '';
321
326
  const subscriptionKeys = new Set();
322
327
  const transformMentionsToTypeAheadItems = makeTransformMentionsToTypeAheadItems({
323
328
  enableAgentSectioning,
@@ -349,6 +354,7 @@ export const createTypeAheadConfig = ({
349
354
  editorState
350
355
  }) {
351
356
  var _api$contextIdentifie, _api$contextIdentifie2;
357
+ lastTypeAheadQuery = query || '';
352
358
  const pluginState = getMentionPluginState(editorState);
353
359
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
354
360
  return Promise.resolve([]);
@@ -398,10 +404,11 @@ export const createTypeAheadConfig = ({
398
404
  if (!enableAgentSectioning) {
399
405
  return [];
400
406
  }
407
+ const applySearchOrder = shouldApplyMentionSearchOrder(lastTypeAheadQuery);
401
408
  return [{
402
409
  id: 'people',
403
410
  title: intl.formatMessage(mentionMessages.typeAheadSectionPeople),
404
- filter: item => {
411
+ filter: applySearchOrder ? isSearchOrderedPersonTypeAheadItem : item => {
405
412
  if (isAgentTypeAheadItem(item)) {
406
413
  return false;
407
414
  }
@@ -422,7 +429,7 @@ export const createTypeAheadConfig = ({
422
429
  }, {
423
430
  id: 'agents',
424
431
  title: intl.formatMessage(mentionMessages.typeAheadSectionAgents),
425
- filter: item => isAgentTypeAheadItem(item),
432
+ filter: applySearchOrder ? isSearchOrderedAgentTypeAheadItem : isAgentTypeAheadItem,
426
433
  limit: 5,
427
434
  sectionTitleDisplay: {
428
435
  showWhenQueryPresent: false,
@@ -435,6 +442,7 @@ export const createTypeAheadConfig = ({
435
442
  },
436
443
  onOpen: () => {
437
444
  firstQueryWithoutResults = null;
445
+ lastTypeAheadQuery = '';
438
446
  },
439
447
  selectItem(state, item, insert, {
440
448
  mode,
@@ -639,6 +647,7 @@ export const createTypeAheadConfig = ({
639
647
  editorState
640
648
  }) => {
641
649
  var _api$contextIdentifie5, _api$contextIdentifie6;
650
+ lastTypeAheadQuery = query || '';
642
651
  const pluginState = getMentionPluginState(editorState);
643
652
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
644
653
  return {
@@ -15,6 +15,55 @@ export const isInviteItem = mention => mention && mention.id === INVITE_ITEM_DES
15
15
  export const isAgentUserType = userType => userType === 'APP' || userType === 'AGENT';
16
16
  export const isAgentMention = mention => isAgentUserType(mention.userType) || mention.appType === 'agent';
17
17
 
18
+ /**
19
+ * True when the mention is explicitly an agent, not a generic APP/bot.
20
+ * Prefer this over {@link isAgentMention} when ordering the search display
21
+ * list behind `platform_editor_mention_search_order` — bare `userType: 'APP'`
22
+ * is a bot unless `appType === 'agent'`.
23
+ */
24
+ export const isExplicitAgentMention = mention => mention.appType === 'agent' || mention.userType === 'AGENT';
25
+
26
+ /**
27
+ * Connect/app bots and teams. Explicit agents are excluded so they can be
28
+ * lifted above this group in the hardcoded display order.
29
+ */
30
+ export const isBotOrTeamMention = mention => {
31
+ if (isExplicitAgentMention(mention)) {
32
+ return false;
33
+ }
34
+ return mention.userType === 'TEAM' || mention.userType === 'APP';
35
+ };
36
+ export const getMentionDisplayGroup = mention => {
37
+ if (isExplicitAgentMention(mention)) {
38
+ return 'agents';
39
+ }
40
+ if (isBotOrTeamMention(mention)) {
41
+ return 'bots-teams';
42
+ }
43
+ return 'people';
44
+ };
45
+
46
+ /**
47
+ * Hardcoded mention display order: people, then agents, then bots/teams.
48
+ * Stable within each group so provider ranking is preserved.
49
+ */
50
+ export const orderMentionsForDisplay = mentions => {
51
+ const people = [];
52
+ const agents = [];
53
+ const botsAndTeams = [];
54
+ for (const mention of mentions) {
55
+ const group = getMentionDisplayGroup(mention);
56
+ if (group === 'agents') {
57
+ agents.push(mention);
58
+ } else if (group === 'bots-teams') {
59
+ botsAndTeams.push(mention);
60
+ } else {
61
+ people.push(mention);
62
+ }
63
+ }
64
+ return [...people, ...agents, ...botsAndTeams];
65
+ };
66
+
18
67
  /**
19
68
  * Actions
20
69
  */
@@ -58,7 +58,7 @@ var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
58
58
  var AGENT_MENTION_INACTIVITY_MS = 3000;
59
59
  var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
60
60
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
61
- var PACKAGE_VERSION = "17.1.4";
61
+ var PACKAGE_VERSION = "17.1.6";
62
62
  var setProvider = function setProvider(provider) {
63
63
  return function (state, dispatch) {
64
64
  if (dispatch) {
@@ -28,10 +28,19 @@ import InviteItem, { INVITE_ITEM_DESCRIPTION } from '../InviteItem';
28
28
  import InviteItemWithEmailDomain from '../InviteItem/InviteItemWithEmailDomain';
29
29
  import { buildTypeAheadCancelPayload, buildTypeAheadInsertedPayload, buildTypeAheadInviteItemClickedPayload, buildTypeAheadInviteItemViewedPayload, buildTypeAheadRenderedPayload } from './analytics';
30
30
  import { MentionItemWithProfileCard } from './MentionItemWithProfileCard';
31
- import { isAgentMention, isInviteItem, isTeamStats, isTeamType, shouldKeepInviteItem } from './utils';
31
+ import { isAgentMention, isBotOrTeamMention, isExplicitAgentMention, isInviteItem, isTeamStats, isTeamType, orderMentionsForDisplay, shouldKeepInviteItem } from './utils';
32
32
  var isAgentTypeAheadItem = function isAgentTypeAheadItem(item) {
33
33
  return item.mention ? isAgentMention(item.mention) : false;
34
34
  };
35
+ var isSearchOrderedAgentTypeAheadItem = function isSearchOrderedAgentTypeAheadItem(item) {
36
+ return !!item.mention && isExplicitAgentMention(item.mention);
37
+ };
38
+ var isSearchOrderedPersonTypeAheadItem = function isSearchOrderedPersonTypeAheadItem(item) {
39
+ return !!item.mention && !isInviteItem(item.mention) && !isExplicitAgentMention(item.mention) && !isBotOrTeamMention(item.mention);
40
+ };
41
+ var shouldApplyMentionSearchOrder = function shouldApplyMentionSearchOrder(query) {
42
+ return isExperimentEnabled('platform_editor_mention_search_order') && query.trim().length > 0;
43
+ };
35
44
 
36
45
  // A non-selectable loading placeholder injected by the provider (e.g.
37
46
  // `RovoChatMentionResource`) while the slower agent source resolves. It
@@ -279,13 +288,14 @@ var makeTransformMentionsToTypeAheadItems = function makeTransformMentionsToType
279
288
  mentionProvider = _ref8.mentionProvider,
280
289
  contextIdentifierProvider = _ref8.contextIdentifierProvider,
281
290
  sessionId = _ref8.sessionId;
282
- var mentionItems = mentions.map(function (mention) {
291
+ var displayMentions = shouldApplyMentionSearchOrder(query) ? orderMentionsForDisplay(mentions) : mentions;
292
+ var mentionItems = displayMentions.map(function (mention) {
283
293
  return toItem(mention);
284
294
  });
285
295
  // The loading placeholder is a rendered-only row — keep it in
286
296
  // `mentionItems` so the shimmer shows, but exclude it from analytics
287
297
  // and no-results bookkeeping so it isn't counted as a real result.
288
- var realMentions = mentions.filter(function (mention) {
298
+ var realMentions = displayMentions.filter(function (mention) {
289
299
  return !isLoadingPlaceholder(mention);
290
300
  });
291
301
  var agentCount = realMentions.filter(isAgentMention).length;
@@ -340,6 +350,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref9) {
340
350
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
341
351
  var sessionId = uuid();
342
352
  var firstQueryWithoutResults = null;
353
+ var lastTypeAheadQuery = '';
343
354
  var subscriptionKeys = new Set();
344
355
  var transformMentionsToTypeAheadItems = makeTransformMentionsToTypeAheadItems({
345
356
  enableAgentSectioning: enableAgentSectioning,
@@ -372,6 +383,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref9) {
372
383
  var _api$contextIdentifie, _api$contextIdentifie2;
373
384
  var query = _ref0.query,
374
385
  editorState = _ref0.editorState;
386
+ lastTypeAheadQuery = query || '';
375
387
  var pluginState = getMentionPluginState(editorState);
376
388
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
377
389
  return Promise.resolve([]);
@@ -418,10 +430,11 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref9) {
418
430
  if (!enableAgentSectioning) {
419
431
  return [];
420
432
  }
433
+ var applySearchOrder = shouldApplyMentionSearchOrder(lastTypeAheadQuery);
421
434
  return [{
422
435
  id: 'people',
423
436
  title: intl.formatMessage(mentionMessages.typeAheadSectionPeople),
424
- filter: function filter(item) {
437
+ filter: applySearchOrder ? isSearchOrderedPersonTypeAheadItem : function (item) {
425
438
  if (isAgentTypeAheadItem(item)) {
426
439
  return false;
427
440
  }
@@ -442,9 +455,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref9) {
442
455
  }, {
443
456
  id: 'agents',
444
457
  title: intl.formatMessage(mentionMessages.typeAheadSectionAgents),
445
- filter: function filter(item) {
446
- return isAgentTypeAheadItem(item);
447
- },
458
+ filter: applySearchOrder ? isSearchOrderedAgentTypeAheadItem : isAgentTypeAheadItem,
448
459
  limit: 5,
449
460
  sectionTitleDisplay: {
450
461
  showWhenQueryPresent: false,
@@ -457,6 +468,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref9) {
457
468
  },
458
469
  onOpen: function onOpen() {
459
470
  firstQueryWithoutResults = null;
471
+ lastTypeAheadQuery = '';
460
472
  },
461
473
  selectItem: function selectItem(state, item, insert, _ref11) {
462
474
  var _api$contextIdentifie3, _api$contextIdentifie4;
@@ -660,6 +672,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref9) {
660
672
  var _api$contextIdentifie5, _api$contextIdentifie6;
661
673
  var query = _ref14.query,
662
674
  editorState = _ref14.editorState;
675
+ lastTypeAheadQuery = query || '';
663
676
  var pluginState = getMentionPluginState(editorState);
664
677
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.mentionProvider)) {
665
678
  return {
@@ -1,3 +1,6 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
1
4
  import { INVITE_ITEM_DESCRIPTION } from '../InviteItem';
2
5
 
3
6
  // Ignored via go/ees005
@@ -25,6 +28,66 @@ export var isAgentMention = function isAgentMention(mention) {
25
28
  return isAgentUserType(mention.userType) || mention.appType === 'agent';
26
29
  };
27
30
 
31
+ /**
32
+ * True when the mention is explicitly an agent, not a generic APP/bot.
33
+ * Prefer this over {@link isAgentMention} when ordering the search display
34
+ * list behind `platform_editor_mention_search_order` — bare `userType: 'APP'`
35
+ * is a bot unless `appType === 'agent'`.
36
+ */
37
+ export var isExplicitAgentMention = function isExplicitAgentMention(mention) {
38
+ return mention.appType === 'agent' || mention.userType === 'AGENT';
39
+ };
40
+
41
+ /**
42
+ * Connect/app bots and teams. Explicit agents are excluded so they can be
43
+ * lifted above this group in the hardcoded display order.
44
+ */
45
+ export var isBotOrTeamMention = function isBotOrTeamMention(mention) {
46
+ if (isExplicitAgentMention(mention)) {
47
+ return false;
48
+ }
49
+ return mention.userType === 'TEAM' || mention.userType === 'APP';
50
+ };
51
+ export var getMentionDisplayGroup = function getMentionDisplayGroup(mention) {
52
+ if (isExplicitAgentMention(mention)) {
53
+ return 'agents';
54
+ }
55
+ if (isBotOrTeamMention(mention)) {
56
+ return 'bots-teams';
57
+ }
58
+ return 'people';
59
+ };
60
+
61
+ /**
62
+ * Hardcoded mention display order: people, then agents, then bots/teams.
63
+ * Stable within each group so provider ranking is preserved.
64
+ */
65
+ export var orderMentionsForDisplay = function orderMentionsForDisplay(mentions) {
66
+ var people = [];
67
+ var agents = [];
68
+ var botsAndTeams = [];
69
+ var _iterator = _createForOfIteratorHelper(mentions),
70
+ _step;
71
+ try {
72
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
73
+ var mention = _step.value;
74
+ var group = getMentionDisplayGroup(mention);
75
+ if (group === 'agents') {
76
+ agents.push(mention);
77
+ } else if (group === 'bots-teams') {
78
+ botsAndTeams.push(mention);
79
+ } else {
80
+ people.push(mention);
81
+ }
82
+ }
83
+ } catch (err) {
84
+ _iterator.e(err);
85
+ } finally {
86
+ _iterator.f();
87
+ }
88
+ return [].concat(people, agents, botsAndTeams);
89
+ };
90
+
28
91
  /**
29
92
  * Actions
30
93
  */
@@ -40,6 +40,8 @@ export interface MentionsPluginOptions extends MentionPluginConfig {
40
40
  *
41
41
  * Consumers own the rollout decision for their editor surface; the shared
42
42
  * mentions plugin only applies the resulting presentation option.
43
+ * Search-time ordering of agents above bots/teams is gated by
44
+ * `platform_editor_mention_search_order`.
43
45
  */
44
46
  enableAgentSectioning?: boolean;
45
47
  /**
@@ -4,6 +4,25 @@ export declare const isTeamStats: (stat: any) => boolean;
4
4
  export declare const isInviteItem: (mention: MentionDescription) => boolean;
5
5
  export declare const isAgentUserType: (userType: string | undefined) => boolean;
6
6
  export declare const isAgentMention: (mention: Pick<MentionDescription, 'appType' | 'userType'>) => boolean;
7
+ /**
8
+ * True when the mention is explicitly an agent, not a generic APP/bot.
9
+ * Prefer this over {@link isAgentMention} when ordering the search display
10
+ * list behind `platform_editor_mention_search_order` — bare `userType: 'APP'`
11
+ * is a bot unless `appType === 'agent'`.
12
+ */
13
+ export declare const isExplicitAgentMention: (mention: Pick<MentionDescription, 'appType' | 'userType'>) => boolean;
14
+ /**
15
+ * Connect/app bots and teams. Explicit agents are excluded so they can be
16
+ * lifted above this group in the hardcoded display order.
17
+ */
18
+ export declare const isBotOrTeamMention: (mention: Pick<MentionDescription, 'appType' | 'userType'>) => boolean;
19
+ export type MentionDisplayGroup = 'people' | 'agents' | 'bots-teams';
20
+ export declare const getMentionDisplayGroup: (mention: Pick<MentionDescription, 'appType' | 'userType'>) => MentionDisplayGroup;
21
+ /**
22
+ * Hardcoded mention display order: people, then agents, then bots/teams.
23
+ * Stable within each group so provider ranking is preserved.
24
+ */
25
+ export declare const orderMentionsForDisplay: <T extends Pick<MentionDescription, 'appType' | 'userType'>>(mentions: readonly T[]) => T[];
7
26
  /**
8
27
  * Actions
9
28
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-mentions",
3
- "version": "17.1.5",
3
+ "version": "17.1.7",
4
4
  "description": "Mentions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  "@atlaskit/editor-plugin-type-ahead": "^16.1.0",
32
32
  "@atlaskit/editor-prosemirror": "^8.0.0",
33
33
  "@atlaskit/feature-gate-js-client": "^6.0.0",
34
- "@atlaskit/icon": "^37.3.0",
34
+ "@atlaskit/icon": "^37.4.0",
35
35
  "@atlaskit/insm": "^2.0.0",
36
36
  "@atlaskit/link": "^5.0.0",
37
37
  "@atlaskit/lozenge": "^15.1.0",
@@ -46,7 +46,7 @@
46
46
  "@atlaskit/profilecard": "^26.18.0",
47
47
  "@atlaskit/teams-app-config": "^2.2.0",
48
48
  "@atlaskit/theme": "^28.0.0",
49
- "@atlaskit/tmp-editor-statsig": "^150.0.0",
49
+ "@atlaskit/tmp-editor-statsig": "^151.0.0",
50
50
  "@atlaskit/tokens": "^16.7.0",
51
51
  "@atlaskit/tooltip": "^24.0.0",
52
52
  "@atlaskit/user-picker": "^13.9.0",