@atlaskit/editor-plugin-mentions 16.0.3 → 16.1.1

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 (36) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/anchored-popup/package.json +10 -0
  3. package/dist/cjs/entry-points/anchored-popup.js +12 -0
  4. package/dist/cjs/mentionsPlugin.js +4 -12
  5. package/dist/cjs/pm-plugins/main.js +1 -1
  6. package/dist/cjs/ui/AnchoredPopup.js +37 -0
  7. package/dist/cjs/ui/InlineInvitePopupContainer.js +157 -0
  8. package/dist/cjs/ui/type-ahead/analytics.js +2 -1
  9. package/dist/cjs/ui/type-ahead/index.js +26 -18
  10. package/dist/es2019/entry-points/anchored-popup.js +2 -0
  11. package/dist/es2019/mentionsPlugin.js +4 -10
  12. package/dist/es2019/pm-plugins/main.js +1 -1
  13. package/dist/es2019/ui/AnchoredPopup.js +28 -0
  14. package/dist/es2019/ui/InlineInvitePopupContainer.js +146 -0
  15. package/dist/es2019/ui/type-ahead/analytics.js +2 -1
  16. package/dist/es2019/ui/type-ahead/index.js +26 -20
  17. package/dist/esm/entry-points/anchored-popup.js +2 -0
  18. package/dist/esm/mentionsPlugin.js +4 -12
  19. package/dist/esm/pm-plugins/main.js +1 -1
  20. package/dist/esm/ui/AnchoredPopup.js +29 -0
  21. package/dist/esm/ui/InlineInvitePopupContainer.js +148 -0
  22. package/dist/esm/ui/type-ahead/analytics.js +2 -1
  23. package/dist/esm/ui/type-ahead/index.js +26 -18
  24. package/dist/types/entry-points/anchored-popup.d.ts +2 -0
  25. package/dist/types/ui/AnchoredPopup.d.ts +13 -0
  26. package/dist/types/ui/InlineInvitePopupContainer.d.ts +11 -0
  27. package/dist/types/ui/type-ahead/analytics.d.ts +1 -1
  28. package/package.json +11 -5
  29. package/dist/cjs/pm-plugins/mentionPlaceholder.js +0 -52
  30. package/dist/cjs/ui/InlineInviteRecaptchaContainer.js +0 -100
  31. package/dist/es2019/pm-plugins/mentionPlaceholder.js +0 -44
  32. package/dist/es2019/ui/InlineInviteRecaptchaContainer.js +0 -90
  33. package/dist/esm/pm-plugins/mentionPlaceholder.js +0 -44
  34. package/dist/esm/ui/InlineInviteRecaptchaContainer.js +0 -91
  35. package/dist/types/pm-plugins/mentionPlaceholder.d.ts +0 -11
  36. package/dist/types/ui/InlineInviteRecaptchaContainer.d.ts +0 -15
@@ -16,7 +16,6 @@ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
16
16
  import { createSingleMentionFragment } from '../../editor-commands';
17
17
  import { mentionPluginKey } from '../../pm-plugins/key';
18
18
  import { ACTIONS } from '../../pm-plugins/main';
19
- import { mentionPlaceholderPluginKey, MENTION_PLACEHOLDER_ACTIONS } from '../../pm-plugins/mentionPlaceholder';
20
19
  import { getMentionPluginState } from '../../pm-plugins/utils';
21
20
  import InviteItem, { INVITE_ITEM_DESCRIPTION } from '../InviteItem';
22
21
  import InviteItemWithEmailDomain from '../InviteItem/InviteItemWithEmailDomain';
@@ -44,7 +43,7 @@ const createInviteItem = ({
44
43
  onHover
45
44
  }) => {
46
45
  var _mentionProvider$getS;
47
- return emailDomain && (_mentionProvider$getS = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS !== void 0 && _mentionProvider$getS.call(mentionProvider) && fg('jira_invites_auto_tag_new_user_in_mentions_fg') ? /*#__PURE__*/React.createElement(InviteItemWithEmailDomain, {
46
+ return emailDomain && (_mentionProvider$getS = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS !== void 0 && _mentionProvider$getS.call(mentionProvider) && fg('inline_invite_from_mentions_kill_switch') ? /*#__PURE__*/React.createElement(InviteItemWithEmailDomain, {
48
47
  productName: mentionProvider ? mentionProvider.productName : undefined,
49
48
  selected: isSelected,
50
49
  onMount: onInviteItemMount,
@@ -137,6 +136,7 @@ const buildAndSendElementsTypeAheadAnalytics = fireEvent => ({
137
136
  query,
138
137
  mentions,
139
138
  stats,
139
+ mentionTypeaheadSessionId,
140
140
  agentAnalytics
141
141
  }) => {
142
142
  let duration = 0;
@@ -163,7 +163,7 @@ const buildAndSendElementsTypeAheadAnalytics = fireEvent => ({
163
163
  memberCount: mention.context.memberCount
164
164
  } : null).filter(m => !!m);
165
165
  }
166
- const payload = buildTypeAheadRenderedPayload(duration, userOrTeamIds, query, teams, xProductMentionsLength, agentAnalytics);
166
+ const payload = buildTypeAheadRenderedPayload(duration, userOrTeamIds, query, teams, xProductMentionsLength, mentionTypeaheadSessionId, agentAnalytics);
167
167
  fireEvent(payload, 'fabric-elements');
168
168
  };
169
169
 
@@ -253,20 +253,20 @@ const makeTransformMentionsToTypeAheadItems = ({
253
253
  sessionId
254
254
  }) => {
255
255
  const mentionItems = mentions.map(mention => toItem(mention));
256
- const agentCount = mentions.filter(isAgentMention).length;
257
- const agentAnalytics = {
258
- agentCount,
259
- agentSectioningEnabled: enableAgentSectioning
260
- };
261
-
262
256
  // The loading placeholder is a rendered-only row — keep it in
263
257
  // `mentionItems` so the shimmer shows, but exclude it from analytics
264
258
  // and no-results bookkeeping so it isn't counted as a real result.
265
259
  const realMentions = mentions.filter(mention => !isLoadingPlaceholder(mention));
260
+ const agentCount = realMentions.filter(isAgentMention).length;
261
+ const agentAnalytics = {
262
+ agentCount,
263
+ agentSectioningEnabled: enableAgentSectioning
264
+ };
266
265
  buildAndSendElementsTypeAheadAnalytics(fireEvent)({
267
266
  query,
268
267
  mentions: realMentions,
269
268
  stats,
269
+ mentionTypeaheadSessionId: sessionId,
270
270
  agentAnalytics
271
271
  });
272
272
 
@@ -460,10 +460,10 @@ export const createTypeAheadConfig = ({
460
460
  // Don't fire event and the callback with selection by space press
461
461
  if (mode !== 'space') {
462
462
  var _mentionProvider$getS3, _mentionProvider$getS4;
463
- fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole, fg('jira_invites_auto_tag_new_user_in_mentions_fg') ? {
463
+ fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole, fg('inline_invite_from_mentions_kill_switch') ? {
464
464
  isInlineInviteMentionsEnabled: (_mentionProvider$getS3 = mentionProvider.getShouldEnableInlineInvite) === null || _mentionProvider$getS3 === void 0 ? void 0 : _mentionProvider$getS3.call(mentionProvider)
465
465
  } : {}));
466
- if ((_mentionProvider$getS4 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS4 !== void 0 && _mentionProvider$getS4.call(mentionProvider) && fg('jira_invites_auto_tag_new_user_in_mentions_fg')) {
466
+ if ((_mentionProvider$getS4 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS4 !== void 0 && _mentionProvider$getS4.call(mentionProvider) && fg('inline_invite_from_mentions_kill_switch')) {
467
467
  // Get the email from query, using the same logic as InviteItemWithEmailDomain
468
468
  const emailDomain = mentionProvider.userEmailDomain;
469
469
  let email = query || '';
@@ -472,15 +472,21 @@ export const createTypeAheadConfig = ({
472
472
  email = `${email.toLowerCase()}@${emailDomain}`;
473
473
  }
474
474
  // If query already includes @, use it as is
475
- if (email && mentionProvider.showInlineInviteRecaptcha) {
476
- mentionProvider.showInlineInviteRecaptcha(email);
477
- const {
478
- tr
479
- } = state;
480
- tr.setMeta(mentionPlaceholderPluginKey, {
481
- action: MENTION_PLACEHOLDER_ACTIONS.SHOW_PLACEHOLDER,
482
- placeholder: `@${query}`
483
- });
475
+ if (email && mentionProvider.showInlineInvitePopup) {
476
+ const pendingLocalId = crypto.randomUUID();
477
+ const tr = insert(createSingleMentionFragment({
478
+ mentionProvider,
479
+ mentionInsertDisplayName,
480
+ tr: state.tr,
481
+ sanitizePrivateContent
482
+ })({
483
+ name: email,
484
+ id: pendingLocalId,
485
+ userType: 'DEFAULT',
486
+ localId: pendingLocalId,
487
+ accessLevel: 'CONTAINER'
488
+ }));
489
+ mentionProvider.showInlineInvitePopup(email, pendingLocalId);
484
490
  return tr;
485
491
  }
486
492
  } else if (mentionProvider.onInviteItemClick) {
@@ -0,0 +1,2 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export { AnchoredPopup } from '../ui/AnchoredPopup';
@@ -23,8 +23,7 @@ import { mentionNodeSpec } from './nodeviews/mentionNodeSpec';
23
23
  import { agentMentionPluginKey, createAgentMentionPlugin } from './pm-plugins/agent';
24
24
  import { mentionPluginKey } from './pm-plugins/key';
25
25
  import { ACTIONS, createMentionPlugin } from './pm-plugins/main';
26
- import { createMentionPlaceholderPlugin } from './pm-plugins/mentionPlaceholder';
27
- import { InlineInviteRecaptchaContainer } from './ui/InlineInviteRecaptchaContainer';
26
+ import { InlineInvitePopupContainer } from './ui/InlineInvitePopupContainer';
28
27
  import { SecondaryToolbarComponent } from './ui/SecondaryToolbarComponent';
29
28
  import { createTypeAheadConfig } from './ui/type-ahead';
30
29
  var processName = function processName(name, intl) {
@@ -137,14 +136,6 @@ var mentionsPlugin = function mentionsPlugin(_ref3) {
137
136
  }
138
137
  });
139
138
  }
140
- if (fg('jira_invites_auto_tag_new_user_in_mentions_fg')) {
141
- plugins.push({
142
- name: 'mentionPlaceholder',
143
- plugin: function plugin() {
144
- return createMentionPlaceholderPlugin();
145
- }
146
- });
147
- }
148
139
  return plugins;
149
140
  },
150
141
  contentComponent: function contentComponent(_ref4) {
@@ -165,9 +156,10 @@ var mentionsPlugin = function mentionsPlugin(_ref3) {
165
156
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Component, {
166
157
  mentionProvider: mentionProvider,
167
158
  api: api
168
- }), fg('jira_invites_auto_tag_new_user_in_mentions_fg') && /*#__PURE__*/React.createElement(InlineInviteRecaptchaContainer, {
159
+ }), fg('inline_invite_from_mentions_kill_switch') && /*#__PURE__*/React.createElement(InlineInvitePopupContainer, {
169
160
  mentionProvider: mentionProvider,
170
- api: api
161
+ api: api,
162
+ editorView: editorView
171
163
  }));
172
164
  }
173
165
  });
@@ -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 = "16.0.2";
61
+ var PACKAGE_VERSION = "16.1.0";
62
62
  var setProvider = function setProvider(provider) {
63
63
  return function (state, dispatch) {
64
64
  if (dispatch) {
@@ -0,0 +1,29 @@
1
+ import React, { useCallback } from 'react';
2
+ import { Popup } from '@atlaskit/popup/popup';
3
+ /**
4
+ * A `<Popup>` anchored to an externally-supplied DOM node. Unlike `PopupTrigger`, it has no
5
+ * clickable trigger of its own — it opens whenever `isOpen` becomes true, so callers can drive
6
+ * it from any external signal.
7
+ */
8
+ export function AnchoredPopup(_ref) {
9
+ var anchorElement = _ref.anchorElement,
10
+ content = _ref.content,
11
+ isOpen = _ref.isOpen,
12
+ onClose = _ref.onClose;
13
+ var renderContent = useCallback(function () {
14
+ return isOpen ? content : null;
15
+ }, [isOpen, content]);
16
+ var renderTrigger = useCallback(function (triggerProps) {
17
+ if (anchorElement && typeof triggerProps.ref === 'function') {
18
+ triggerProps.ref(anchorElement);
19
+ }
20
+ return null;
21
+ }, [anchorElement]);
22
+ return /*#__PURE__*/React.createElement(Popup, {
23
+ isOpen: isOpen,
24
+ onClose: onClose,
25
+ placement: "bottom-start",
26
+ content: renderContent,
27
+ trigger: renderTrigger
28
+ });
29
+ }
@@ -0,0 +1,148 @@
1
+ /* InlineInvitePopupContainer.tsx generated by @compiled/babel-plugin v2.0.0 */
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import { ax, ix } from "@compiled/react/runtime";
4
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
5
+ var findMentionRange = function findMentionRange(doc, localId) {
6
+ var range = null;
7
+ doc.descendants(function (node, pos) {
8
+ if (range) {
9
+ return false;
10
+ }
11
+ if (node.type.name === 'mention' && node.attrs.localId === localId) {
12
+ range = {
13
+ from: pos,
14
+ to: pos + node.nodeSize
15
+ };
16
+ return false;
17
+ }
18
+ return true;
19
+ });
20
+ return range;
21
+ };
22
+ export var InlineInvitePopupContainer = function InlineInvitePopupContainer(_ref) {
23
+ var _api$mention2, _api$core3;
24
+ var mentionProvider = _ref.mentionProvider,
25
+ api = _ref.api,
26
+ editorView = _ref.editorView;
27
+ var _useState = useState(null),
28
+ _useState2 = _slicedToArray(_useState, 2),
29
+ provider = _useState2[0],
30
+ setProvider = _useState2[1];
31
+ var _useState3 = useState(null),
32
+ _useState4 = _slicedToArray(_useState3, 2),
33
+ anchorElement = _useState4[0],
34
+ setAnchorElement = _useState4[1];
35
+ var pendingMentionRef = useRef(null);
36
+ useEffect(function () {
37
+ if (!mentionProvider) {
38
+ return;
39
+ }
40
+ var isMounted = true;
41
+ var cleanupProvider;
42
+ mentionProvider.then(function (resolvedProvider) {
43
+ var _providerWithPopup$ge;
44
+ if (!isMounted) {
45
+ return;
46
+ }
47
+ var providerWithPopup = resolvedProvider;
48
+ var originalGetMentionDisabledState = (_providerWithPopup$ge = providerWithPopup.getMentionDisabledState) === null || _providerWithPopup$ge === void 0 ? void 0 : _providerWithPopup$ge.bind(providerWithPopup);
49
+ providerWithPopup.getMentionDisabledState = function (mention) {
50
+ var _pendingMentionRef$cu;
51
+ if (((_pendingMentionRef$cu = pendingMentionRef.current) === null || _pendingMentionRef$cu === void 0 ? void 0 : _pendingMentionRef$cu.localId) === mention.id) {
52
+ return {
53
+ disabled: true
54
+ };
55
+ }
56
+ return originalGetMentionDisabledState === null || originalGetMentionDisabledState === void 0 ? void 0 : originalGetMentionDisabledState(mention);
57
+ };
58
+ cleanupProvider = function cleanupProvider() {
59
+ if (originalGetMentionDisabledState) {
60
+ providerWithPopup.getMentionDisabledState = originalGetMentionDisabledState;
61
+ } else {
62
+ delete providerWithPopup.getMentionDisabledState;
63
+ }
64
+ };
65
+ setProvider(providerWithPopup);
66
+ }).catch(function () {});
67
+ return function () {
68
+ var _cleanupProvider;
69
+ isMounted = false;
70
+ (_cleanupProvider = cleanupProvider) === null || _cleanupProvider === void 0 || _cleanupProvider();
71
+ setProvider(null);
72
+ };
73
+ }, [mentionProvider]);
74
+ var removePendingMention = useCallback(function () {
75
+ var _api$core;
76
+ var pending = pendingMentionRef.current;
77
+ if (pending && api !== null && api !== void 0 && (_api$core = api.core) !== null && _api$core !== void 0 && (_api$core = _api$core.actions) !== null && _api$core !== void 0 && _api$core.execute) {
78
+ api.core.actions.execute(function (_ref2) {
79
+ var tr = _ref2.tr;
80
+ var range = findMentionRange(tr.doc, pending.localId);
81
+ return range ? tr.delete(range.from, range.to) : null;
82
+ });
83
+ }
84
+ pendingMentionRef.current = null;
85
+ setAnchorElement(null);
86
+ }, [api]);
87
+ var handleDismiss = useCallback(function () {
88
+ removePendingMention();
89
+ }, [removePendingMention]);
90
+ var handleInviteComplete = useCallback(function (result) {
91
+ var _result$invited$, _api$core2, _api$mention;
92
+ var pending = pendingMentionRef.current;
93
+ if (!pending) {
94
+ return;
95
+ }
96
+ var invitedUser = (_result$invited$ = result.invited[0]) !== null && _result$invited$ !== void 0 ? _result$invited$ : result.requested[0];
97
+ if (!invitedUser || !(api !== null && api !== void 0 && (_api$core2 = api.core) !== null && _api$core2 !== void 0 && (_api$core2 = _api$core2.actions) !== null && _api$core2 !== void 0 && _api$core2.execute) || !(api !== null && api !== void 0 && (_api$mention = api.mention) !== null && _api$mention !== void 0 && (_api$mention = _api$mention.commands) !== null && _api$mention !== void 0 && _api$mention.insertMention)) {
98
+ removePendingMention();
99
+ return;
100
+ }
101
+ var userId = invitedUser.id,
102
+ email = invitedUser.email;
103
+ api.core.actions.execute(function (_ref3) {
104
+ var tr = _ref3.tr;
105
+ var range = findMentionRange(tr.doc, pending.localId);
106
+ return range ? tr.delete(range.from, range.to) : null;
107
+ });
108
+ api.core.actions.execute(api.mention.commands.insertMention({
109
+ id: userId,
110
+ name: email,
111
+ userType: 'DEFAULT',
112
+ accessLevel: 'CONTAINER'
113
+ }));
114
+ pendingMentionRef.current = null;
115
+ setAnchorElement(null);
116
+ }, [api, removePendingMention]);
117
+ var handleReady = useCallback(function (show) {
118
+ if (!provider) {
119
+ return;
120
+ }
121
+ if (show) {
122
+ provider.showInlineInvitePopup = function (email, localId) {
123
+ pendingMentionRef.current = {
124
+ email: email,
125
+ localId: localId
126
+ };
127
+ setTimeout(function () {
128
+ var range = findMentionRange(editorView.state.doc, localId);
129
+ var dom = range ? editorView.nodeDOM(range.from) : null;
130
+ setAnchorElement(dom instanceof HTMLElement ? dom : null);
131
+ show(email);
132
+ }, 0);
133
+ };
134
+ } else {
135
+ delete provider.showInlineInvitePopup;
136
+ }
137
+ }, [provider, editorView]);
138
+ if (!(provider !== null && provider !== void 0 && provider.InlineInvitePopup) || !(api !== null && api !== void 0 && (_api$mention2 = api.mention) !== null && _api$mention2 !== void 0 && (_api$mention2 = _api$mention2.commands) !== null && _api$mention2 !== void 0 && _api$mention2.insertMention) || !(api !== null && api !== void 0 && (_api$core3 = api.core) !== null && _api$core3 !== void 0 && (_api$core3 = _api$core3.actions) !== null && _api$core3 !== void 0 && _api$core3.execute)) {
139
+ return null;
140
+ }
141
+ var PopupComponent = provider.InlineInvitePopup;
142
+ return /*#__PURE__*/React.createElement(PopupComponent, {
143
+ anchorElement: anchorElement,
144
+ onInviteComplete: handleInviteComplete,
145
+ onDismiss: handleDismiss,
146
+ onReady: handleReady
147
+ });
148
+ };
@@ -146,7 +146,7 @@ export var buildTypeAheadInsertedPayload = function buildTypeAheadInsertedPayloa
146
146
  })
147
147
  };
148
148
  };
149
- export var buildTypeAheadRenderedPayload = function buildTypeAheadRenderedPayload(duration, userIds, query, teams, xProductMentionsLength, agentAnalytics) {
149
+ export var buildTypeAheadRenderedPayload = function buildTypeAheadRenderedPayload(duration, userIds, query, teams, xProductMentionsLength, mentionTypeaheadSessionId, agentAnalytics) {
150
150
  var _extractAttributesFro4 = extractAttributesFromQuery(query),
151
151
  queryLength = _extractAttributesFro4.queryLength,
152
152
  spaceInQuery = _extractAttributesFro4.spaceInQuery;
@@ -163,6 +163,7 @@ export var buildTypeAheadRenderedPayload = function buildTypeAheadRenderedPayloa
163
163
  attributes: _objectSpread({
164
164
  componentName: componentName,
165
165
  duration: duration,
166
+ mentionTypeaheadSessionId: mentionTypeaheadSessionId,
166
167
  userIds: userIds,
167
168
  teams: teams,
168
169
  queryLength: queryLength,
@@ -23,7 +23,6 @@ import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
23
23
  import { createSingleMentionFragment } from '../../editor-commands';
24
24
  import { mentionPluginKey } from '../../pm-plugins/key';
25
25
  import { ACTIONS } from '../../pm-plugins/main';
26
- import { mentionPlaceholderPluginKey, MENTION_PLACEHOLDER_ACTIONS } from '../../pm-plugins/mentionPlaceholder';
27
26
  import { getMentionPluginState } from '../../pm-plugins/utils';
28
27
  import InviteItem, { INVITE_ITEM_DESCRIPTION } from '../InviteItem';
29
28
  import InviteItemWithEmailDomain from '../InviteItem/InviteItemWithEmailDomain';
@@ -58,7 +57,7 @@ var createInviteItem = function createInviteItem(_ref) {
58
57
  var isSelected = _ref2.isSelected,
59
58
  onClick = _ref2.onClick,
60
59
  onHover = _ref2.onHover;
61
- return emailDomain && (_mentionProvider$getS = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS !== void 0 && _mentionProvider$getS.call(mentionProvider) && fg('jira_invites_auto_tag_new_user_in_mentions_fg') ? /*#__PURE__*/React.createElement(InviteItemWithEmailDomain, {
60
+ return emailDomain && (_mentionProvider$getS = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS !== void 0 && _mentionProvider$getS.call(mentionProvider) && fg('inline_invite_from_mentions_kill_switch') ? /*#__PURE__*/React.createElement(InviteItemWithEmailDomain, {
62
61
  productName: mentionProvider ? mentionProvider.productName : undefined,
63
62
  selected: isSelected,
64
63
  onMount: onInviteItemMount,
@@ -159,6 +158,7 @@ var buildAndSendElementsTypeAheadAnalytics = function buildAndSendElementsTypeAh
159
158
  var query = _ref5.query,
160
159
  mentions = _ref5.mentions,
161
160
  stats = _ref5.stats,
161
+ mentionTypeaheadSessionId = _ref5.mentionTypeaheadSessionId,
162
162
  agentAnalytics = _ref5.agentAnalytics;
163
163
  var duration = 0;
164
164
  var userOrTeamIds = null;
@@ -192,7 +192,7 @@ var buildAndSendElementsTypeAheadAnalytics = function buildAndSendElementsTypeAh
192
192
  return !!m;
193
193
  });
194
194
  }
195
- var payload = buildTypeAheadRenderedPayload(duration, userOrTeamIds, query, teams, xProductMentionsLength, agentAnalytics);
195
+ var payload = buildTypeAheadRenderedPayload(duration, userOrTeamIds, query, teams, xProductMentionsLength, mentionTypeaheadSessionId, agentAnalytics);
196
196
  fireEvent(payload, 'fabric-elements');
197
197
  };
198
198
  };
@@ -277,22 +277,22 @@ var makeTransformMentionsToTypeAheadItems = function makeTransformMentionsToType
277
277
  var mentionItems = mentions.map(function (mention) {
278
278
  return toItem(mention);
279
279
  });
280
- var agentCount = mentions.filter(isAgentMention).length;
281
- var agentAnalytics = {
282
- agentCount: agentCount,
283
- agentSectioningEnabled: enableAgentSectioning
284
- };
285
-
286
280
  // The loading placeholder is a rendered-only row — keep it in
287
281
  // `mentionItems` so the shimmer shows, but exclude it from analytics
288
282
  // and no-results bookkeeping so it isn't counted as a real result.
289
283
  var realMentions = mentions.filter(function (mention) {
290
284
  return !isLoadingPlaceholder(mention);
291
285
  });
286
+ var agentCount = realMentions.filter(isAgentMention).length;
287
+ var agentAnalytics = {
288
+ agentCount: agentCount,
289
+ agentSectioningEnabled: enableAgentSectioning
290
+ };
292
291
  buildAndSendElementsTypeAheadAnalytics(fireEvent)({
293
292
  query: query,
294
293
  mentions: realMentions,
295
294
  stats: stats,
295
+ mentionTypeaheadSessionId: sessionId,
296
296
  agentAnalytics: agentAnalytics
297
297
  });
298
298
 
@@ -481,10 +481,10 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref8) {
481
481
  // Don't fire event and the callback with selection by space press
482
482
  if (mode !== 'space') {
483
483
  var _mentionProvider$getS3, _mentionProvider$getS4;
484
- fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole, fg('jira_invites_auto_tag_new_user_in_mentions_fg') ? {
484
+ fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole, fg('inline_invite_from_mentions_kill_switch') ? {
485
485
  isInlineInviteMentionsEnabled: (_mentionProvider$getS3 = mentionProvider.getShouldEnableInlineInvite) === null || _mentionProvider$getS3 === void 0 ? void 0 : _mentionProvider$getS3.call(mentionProvider)
486
486
  } : {}));
487
- if ((_mentionProvider$getS4 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS4 !== void 0 && _mentionProvider$getS4.call(mentionProvider) && fg('jira_invites_auto_tag_new_user_in_mentions_fg')) {
487
+ if ((_mentionProvider$getS4 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS4 !== void 0 && _mentionProvider$getS4.call(mentionProvider) && fg('inline_invite_from_mentions_kill_switch')) {
488
488
  // Get the email from query, using the same logic as InviteItemWithEmailDomain
489
489
  var emailDomain = mentionProvider.userEmailDomain;
490
490
  var email = query || '';
@@ -493,13 +493,21 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref8) {
493
493
  email = "".concat(email.toLowerCase(), "@").concat(emailDomain);
494
494
  }
495
495
  // If query already includes @, use it as is
496
- if (email && mentionProvider.showInlineInviteRecaptcha) {
497
- mentionProvider.showInlineInviteRecaptcha(email);
498
- var _tr = state.tr;
499
- _tr.setMeta(mentionPlaceholderPluginKey, {
500
- action: MENTION_PLACEHOLDER_ACTIONS.SHOW_PLACEHOLDER,
501
- placeholder: "@".concat(query)
502
- });
496
+ if (email && mentionProvider.showInlineInvitePopup) {
497
+ var pendingLocalId = crypto.randomUUID();
498
+ var _tr = insert(createSingleMentionFragment({
499
+ mentionProvider: mentionProvider,
500
+ mentionInsertDisplayName: mentionInsertDisplayName,
501
+ tr: state.tr,
502
+ sanitizePrivateContent: sanitizePrivateContent
503
+ })({
504
+ name: email,
505
+ id: pendingLocalId,
506
+ userType: 'DEFAULT',
507
+ localId: pendingLocalId,
508
+ accessLevel: 'CONTAINER'
509
+ }));
510
+ mentionProvider.showInlineInvitePopup(email, pendingLocalId);
503
511
  return _tr;
504
512
  }
505
513
  } else if (mentionProvider.onInviteItemClick) {
@@ -0,0 +1,2 @@
1
+ export { AnchoredPopup } from '../ui/AnchoredPopup';
2
+ export type { AnchoredPopupProps } from '../ui/AnchoredPopup';
@@ -0,0 +1,13 @@
1
+ import { type ReactNode } from 'react';
2
+ export type AnchoredPopupProps = {
3
+ anchorElement: HTMLElement | null;
4
+ content: ReactNode;
5
+ isOpen: boolean;
6
+ onClose: () => void;
7
+ };
8
+ /**
9
+ * A `<Popup>` anchored to an externally-supplied DOM node. Unlike `PopupTrigger`, it has no
10
+ * clickable trigger of its own — it opens whenever `isOpen` becomes true, so callers can drive
11
+ * it from any external signal.
12
+ */
13
+ export declare function AnchoredPopup({ anchorElement, content, isOpen, onClose, }: AnchoredPopupProps): JSX.Element;
@@ -0,0 +1,11 @@
1
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ import type { MentionProvider } from '@atlaskit/mention/resource';
4
+ import type { MentionsPlugin } from '../mentionsPluginType';
5
+ interface Props {
6
+ api: ExtractInjectionAPI<MentionsPlugin> | undefined;
7
+ editorView: EditorView;
8
+ mentionProvider: Promise<MentionProvider> | undefined;
9
+ }
10
+ export declare const InlineInvitePopupContainer: ({ mentionProvider, api, editorView, }: Props) => JSX.Element | null;
11
+ export {};
@@ -9,7 +9,7 @@ export declare const buildTypeAheadCancelPayload: (duration: number, upKeyCount:
9
9
  export declare const buildTypeAheadInviteItemViewedPayload: (sessionId: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole, additionalAttributes?: Record<string, unknown>) => AnalyticsEventPayload;
10
10
  export declare const buildTypeAheadInviteItemClickedPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, insertType: SelectItemMode, query?: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole, additionalAttributes?: Record<string, unknown>) => AnalyticsEventPayload;
11
11
  export declare const buildTypeAheadInsertedPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, insertType: SelectItemMode, mention: MentionDescription, mentionLocalId: string, mentionList?: MentionDescription[], query?: string, contextIdentifierProvider?: ContextIdentifierProvider, taskListId?: string, taskItemId?: string, isAgent?: boolean, agentSectioningEnabled?: boolean) => AnalyticsEventPayload;
12
- export declare const buildTypeAheadRenderedPayload: (duration: number, userIds: Array<string> | null, query: string, teams: TeamInfoAttrAnalytics[] | null, xProductMentionsLength: number, agentAnalytics?: {
12
+ export declare const buildTypeAheadRenderedPayload: (duration: number, userIds: Array<string> | null, query: string, teams: TeamInfoAttrAnalytics[] | null, xProductMentionsLength: number, mentionTypeaheadSessionId: string, agentAnalytics?: {
13
13
  agentCount: number;
14
14
  agentSectioningEnabled: boolean;
15
15
  }) => AnalyticsEventPayload;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-mentions",
3
- "version": "16.0.3",
3
+ "version": "16.1.1",
4
4
  "description": "Mentions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -34,17 +34,18 @@
34
34
  "@atlaskit/insm": "^1.2.0",
35
35
  "@atlaskit/link": "^5.0.0",
36
36
  "@atlaskit/lozenge": "^15.0.0",
37
- "@atlaskit/mention": "^27.14.0",
37
+ "@atlaskit/mention": "^27.15.0",
38
38
  "@atlaskit/platform-feature-experiments": "^0.3.0",
39
39
  "@atlaskit/platform-feature-flags": "^2.1.0",
40
40
  "@atlaskit/popper": "^9.1.0",
41
+ "@atlaskit/popup": "^6.0.0",
41
42
  "@atlaskit/portal": "^6.2.0",
42
43
  "@atlaskit/primitives": "^22.2.0",
43
44
  "@atlaskit/profilecard": "^26.16.0",
44
45
  "@atlaskit/teams-app-config": "^2.2.0",
45
46
  "@atlaskit/theme": "^28.0.0",
46
- "@atlaskit/tmp-editor-statsig": "^144.0.0",
47
- "@atlaskit/tokens": "^16.4.0",
47
+ "@atlaskit/tmp-editor-statsig": "^145.0.0",
48
+ "@atlaskit/tokens": "^16.5.0",
48
49
  "@atlaskit/tooltip": "^24.0.0",
49
50
  "@atlaskit/user-picker": "^13.8.0",
50
51
  "@babel/runtime": "^7.0.0",
@@ -55,12 +56,14 @@
55
56
  "uuid": "^3.1.0"
56
57
  },
57
58
  "peerDependencies": {
58
- "@atlaskit/editor-common": "^118.1.0",
59
+ "@atlaskit/editor-common": "^118.3.0",
59
60
  "react": "^18.2.0 || ^19.2.0",
60
61
  "react-dom": "^18.2.0 || ^19.2.0",
61
62
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
62
63
  },
63
64
  "devDependencies": {
65
+ "@atlaskit/button": "^25.0.0",
66
+ "@atlaskit/editor-core": "^223.0.0",
64
67
  "@testing-library/react": "^16.3.0",
65
68
  "react": "^19.2.0",
66
69
  "react-dom": "^19.2.0",
@@ -117,6 +120,9 @@
117
120
  "jira_invites_auto_tag_new_user_in_mentions_fg": {
118
121
  "type": "boolean"
119
122
  },
123
+ "inline_invite_from_mentions_kill_switch": {
124
+ "type": "boolean"
125
+ },
120
126
  "people-teams_migrate-user-profile-card": {
121
127
  "type": "boolean"
122
128
  },
@@ -1,52 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.MENTION_PLACEHOLDER_ACTIONS = void 0;
7
- exports.createMentionPlaceholderPlugin = createMentionPlaceholderPlugin;
8
- exports.mentionPlaceholderPluginKey = void 0;
9
- var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
10
- var _state = require("@atlaskit/editor-prosemirror/state");
11
- var _view = require("@atlaskit/editor-prosemirror/view");
12
- var mentionPlaceholderPluginKey = exports.mentionPlaceholderPluginKey = new _state.PluginKey('mentionPlaceholderPlugin');
13
- var MENTION_PLACEHOLDER_ACTIONS = exports.MENTION_PLACEHOLDER_ACTIONS = {
14
- SHOW_PLACEHOLDER: 'SHOW_PLACEHOLDER',
15
- HIDE_PLACEHOLDER: 'HIDE_PLACEHOLDER'
16
- };
17
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
18
- function createMentionPlaceholderPlugin() {
19
- return new _safePlugin.SafePlugin({
20
- key: mentionPlaceholderPluginKey,
21
- state: {
22
- init: function init() {
23
- return {};
24
- },
25
- apply: function apply(tr, pluginState) {
26
- var meta = tr.getMeta(mentionPlaceholderPluginKey);
27
- if ((meta === null || meta === void 0 ? void 0 : meta.action) === MENTION_PLACEHOLDER_ACTIONS.SHOW_PLACEHOLDER) {
28
- return {
29
- placeholder: meta.placeholder
30
- };
31
- }
32
- if ((meta === null || meta === void 0 ? void 0 : meta.action) === MENTION_PLACEHOLDER_ACTIONS.HIDE_PLACEHOLDER) {
33
- return {};
34
- }
35
- return pluginState;
36
- }
37
- },
38
- props: {
39
- decorations: function decorations(state) {
40
- var pluginState = mentionPlaceholderPluginKey.getState(state);
41
- if (pluginState !== null && pluginState !== void 0 && pluginState.placeholder) {
42
- var selection = state.selection;
43
- var span = document.createElement('span');
44
- span.textContent = pluginState.placeholder;
45
- span.style.setProperty('color', "var(--ds-text-accent-blue, #1558BC)");
46
- return _view.DecorationSet.create(state.doc, [_view.Decoration.widget(selection.from, span)]);
47
- }
48
- return null;
49
- }
50
- }
51
- });
52
- }