@atlaskit/editor-plugin-mentions 9.1.8 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-mentions
2
2
 
3
+ ## 9.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`24eaee764c0df`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/24eaee764c0df) -
8
+ [ux] Inline invites for mentions in editor.
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies
13
+
14
+ ## 9.1.9
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+
3
20
  ## 9.1.8
4
21
 
5
22
  ### Patch Changes
@@ -23,6 +23,7 @@ var _editorCommands = require("./editor-commands");
23
23
  var _mentionNodeSpec = require("./nodeviews/mentionNodeSpec");
24
24
  var _key = require("./pm-plugins/key");
25
25
  var _main = require("./pm-plugins/main");
26
+ var _InlineInviteRecaptchaContainer = require("./ui/InlineInviteRecaptchaContainer");
26
27
  var _SecondaryToolbarComponent = require("./ui/SecondaryToolbarComponent");
27
28
  var _typeAhead = require("./ui/type-ahead");
28
29
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
@@ -137,10 +138,13 @@ var mentionsPlugin = exports.mentionsPlugin = function mentionsPlugin(_ref3) {
137
138
  providerFactory: providerFactory,
138
139
  renderNode: function renderNode(_ref5) {
139
140
  var mentionProvider = _ref5.mentionProvider;
140
- return /*#__PURE__*/_react.default.createElement(Component, {
141
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(Component, {
141
142
  mentionProvider: mentionProvider,
142
143
  api: api
143
- });
144
+ }), (0, _platformFeatureFlags.fg)('jira_invites_auto_tag_new_user_in_mentions_fg') && /*#__PURE__*/_react.default.createElement(_InlineInviteRecaptchaContainer.InlineInviteRecaptchaContainer, {
145
+ mentionProvider: mentionProvider,
146
+ api: api
147
+ }));
144
148
  }
145
149
  });
146
150
  },
@@ -0,0 +1,82 @@
1
+ /* InlineInviteRecaptchaContainer.tsx generated by @compiled/babel-plugin v0.38.1 */
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ exports.InlineInviteRecaptchaContainer = void 0;
10
+ var _runtime = require("@compiled/react/runtime");
11
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
12
+ var _react = _interopRequireWildcard(require("react"));
13
+ var _analytics = require("../ui/type-ahead/analytics");
14
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
15
+ /**
16
+ * Container that renders the recaptcha component from the mention provider and manages handleSuccess.
17
+ * Does NOT pass email - the provider's component uses useInlineInviteRecaptcha hook internally
18
+ * and wires showRecaptcha to the provider. When user clicks invite item, type-ahead calls
19
+ * mentionProvider.showInlineInviteRecaptcha(email) which passes email to the component.
20
+ */
21
+ var InlineInviteRecaptchaContainer = exports.InlineInviteRecaptchaContainer = function InlineInviteRecaptchaContainer(_ref) {
22
+ var _api$mention2, _api$core2;
23
+ var mentionProvider = _ref.mentionProvider,
24
+ api = _ref.api;
25
+ var _useState = (0, _react.useState)(null),
26
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
27
+ provider = _useState2[0],
28
+ setProvider = _useState2[1];
29
+ (0, _react.useEffect)(function () {
30
+ if (!mentionProvider) {
31
+ return;
32
+ }
33
+ var isMounted = true;
34
+ mentionProvider.then(function (resolvedProvider) {
35
+ if (!isMounted) {
36
+ return;
37
+ }
38
+ setProvider(resolvedProvider);
39
+ }).catch(function () {
40
+ // Silently handle promise rejection
41
+ });
42
+ return function () {
43
+ isMounted = false;
44
+ setProvider(null);
45
+ };
46
+ }, [mentionProvider]);
47
+ var handleSuccess = (0, _react.useCallback)(function (userId, email) {
48
+ var _api$mention, _api$core;
49
+ if (!(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) || !(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)) {
50
+ return;
51
+ }
52
+ var name = email.split('@')[0] || email;
53
+ api.core.actions.execute(api.mention.commands.insertMention({
54
+ id: userId,
55
+ name: name,
56
+ userType: 'DEFAULT',
57
+ accessLevel: 'CONTAINER'
58
+ }));
59
+ }, [api]);
60
+ var handleClose = (0, _react.useCallback)(function () {
61
+ // No-op: recaptcha state is managed by the hook-based component
62
+ }, []);
63
+ var handleReady = (0, _react.useCallback)(function (showRecaptcha) {
64
+ if (provider) {
65
+ if (showRecaptcha) {
66
+ provider.showInlineInviteRecaptcha = showRecaptcha;
67
+ } else {
68
+ delete provider.showInlineInviteRecaptcha;
69
+ }
70
+ }
71
+ }, [provider]);
72
+ if (!(provider !== null && provider !== void 0 && provider.InlineInviteRecaptcha) || !(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$core2 = api.core) !== null && _api$core2 !== void 0 && (_api$core2 = _api$core2.actions) !== null && _api$core2 !== void 0 && _api$core2.execute)) {
73
+ return null;
74
+ }
75
+ var RecaptchaComponent = provider.InlineInviteRecaptcha;
76
+ return /*#__PURE__*/_react.default.createElement(RecaptchaComponent, {
77
+ analyticsSource: _analytics.MENTION_SOURCE,
78
+ onSuccess: handleSuccess,
79
+ onClose: handleClose,
80
+ onReady: handleReady
81
+ });
82
+ };
@@ -166,7 +166,7 @@ var InviteItemWithEmailDomain = function InviteItemWithEmailDomain(_ref) {
166
166
  };
167
167
  }, [query, isEmailValid]);
168
168
  var displayName = query && emailDomain ? possibleEmail : undefined;
169
- return /*#__PURE__*/_react.default.createElement("div", {
169
+ return displayName && /*#__PURE__*/_react.default.createElement("div", {
170
170
  role: "button",
171
171
  tabIndex: 0,
172
172
  onMouseDown: onSelected,
@@ -191,19 +191,8 @@ var InviteItemWithEmailDomain = function InviteItemWithEmailDomain(_ref) {
191
191
  })), /*#__PURE__*/_react.default.createElement("div", {
192
192
  "data-testid": "name-section",
193
193
  className: (0, _runtime.ax)([style.nameSection])
194
- }, displayName ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", null, displayName), /*#__PURE__*/_react.default.createElement("div", {
194
+ }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", null, displayName), /*#__PURE__*/_react.default.createElement("div", {
195
195
  className: (0, _runtime.ax)([style.byline])
196
- }, getByline())) : /*#__PURE__*/_react.default.createElement(_reactIntlNext.FormattedMessage
197
- // Ignored via go/ees005
198
- // eslint-disable-next-line react/jsx-props-no-spreading
199
- , (0, _extends2.default)({}, _messages.mentionMessages.inviteItemTitle, {
200
- values: {
201
- userRole: userRole || 'basic',
202
- productName: /*#__PURE__*/_react.default.createElement("span", {
203
- "data-testid": "capitalized-message",
204
- className: (0, _runtime.ax)([style.capitalize])
205
- }, productName)
206
- }
207
- })))));
196
+ }, getByline())))));
208
197
  };
209
198
  var _default = exports.default = (0, _reactIntlNext.injectIntl)(InviteItemWithEmailDomain);
@@ -3,12 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.buildTypeAheadRenderedPayload = exports.buildTypeAheadInviteItemViewedPayload = exports.buildTypeAheadInviteItemClickedPayload = exports.buildTypeAheadInsertedPayload = exports.buildTypeAheadCancelPayload = void 0;
6
+ exports.buildTypeAheadRenderedPayload = exports.buildTypeAheadInviteItemViewedPayload = exports.buildTypeAheadInviteItemClickedPayload = exports.buildTypeAheadInsertedPayload = exports.buildTypeAheadCancelPayload = exports.MENTION_SOURCE = void 0;
7
7
  var _analytics = require("@atlaskit/editor-common/analytics");
8
8
  var _resource = require("@atlaskit/mention/resource");
9
9
  var _utils = require("./utils");
10
10
  var componentName = 'mention';
11
- var source = 'mentionInEditor';
11
+ var MENTION_SOURCE = exports.MENTION_SOURCE = 'mentionInEditor';
12
12
  var emptyQueryResponse = {
13
13
  queryLength: 0,
14
14
  spaceInQuery: false
@@ -69,7 +69,7 @@ var buildTypeAheadInviteItemViewedPayload = exports.buildTypeAheadInviteItemView
69
69
  childObjectId: childObjectId,
70
70
  userRole: userRole,
71
71
  sessionId: sessionId,
72
- source: source
72
+ source: MENTION_SOURCE
73
73
  }
74
74
  };
75
75
  };
@@ -343,8 +343,22 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
343
343
  if (mentionProvider && mentionProvider.shouldEnableInvite && (0, _utils3.isInviteItem)(item.mention)) {
344
344
  // Don't fire event and the callback with selection by space press
345
345
  if (mode !== 'space') {
346
+ var _mentionProvider$getS2;
346
347
  fireEvent((0, _analytics.buildTypeAheadInviteItemClickedPayload)(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole));
347
- if (mentionProvider.onInviteItemClick) {
348
+ if ((_mentionProvider$getS2 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS2 !== void 0 && _mentionProvider$getS2.call(mentionProvider) && (0, _platformFeatureFlags.fg)('jira_invites_auto_tag_new_user_in_mentions_fg')) {
349
+ // Get the email from query, using the same logic as InviteItemWithEmailDomain
350
+ var emailDomain = mentionProvider.userEmailDomain;
351
+ var email = query || '';
352
+ // If query doesn't include @ and we have an email domain, append it
353
+ if (email && !email.includes('@') && emailDomain) {
354
+ email = "".concat(email.toLowerCase(), "@").concat(emailDomain);
355
+ }
356
+ // If query already includes @, use it as is
357
+ if (email && mentionProvider.showInlineInviteRecaptcha) {
358
+ mentionProvider.showInlineInviteRecaptcha(email);
359
+ }
360
+ } else if (mentionProvider.onInviteItemClick) {
361
+ // Fallback to old behavior for backward compatibility
348
362
  mentionProvider.onInviteItemClick('mention');
349
363
  }
350
364
  }
@@ -13,6 +13,7 @@ import { insertMention } from './editor-commands';
13
13
  import { mentionNodeSpec } from './nodeviews/mentionNodeSpec';
14
14
  import { mentionPluginKey } from './pm-plugins/key';
15
15
  import { ACTIONS, createMentionPlugin } from './pm-plugins/main';
16
+ import { InlineInviteRecaptchaContainer } from './ui/InlineInviteRecaptchaContainer';
16
17
  import { SecondaryToolbarComponent } from './ui/SecondaryToolbarComponent';
17
18
  import { createTypeAheadConfig } from './ui/type-ahead';
18
19
  const processName = (name, intl) => {
@@ -135,10 +136,13 @@ const mentionsPlugin = ({
135
136
  renderNode: ({
136
137
  mentionProvider
137
138
  }) => {
138
- return /*#__PURE__*/React.createElement(Component, {
139
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Component, {
139
140
  mentionProvider: mentionProvider,
140
141
  api: api
141
- });
142
+ }), fg('jira_invites_auto_tag_new_user_in_mentions_fg') && /*#__PURE__*/React.createElement(InlineInviteRecaptchaContainer, {
143
+ mentionProvider: mentionProvider,
144
+ api: api
145
+ }));
142
146
  }
143
147
  });
144
148
  },
@@ -0,0 +1,70 @@
1
+ /* InlineInviteRecaptchaContainer.tsx generated by @compiled/babel-plugin v0.38.1 */
2
+ import { ax, ix } from "@compiled/react/runtime";
3
+ import React, { useCallback, useEffect, useState } from 'react';
4
+ import { MENTION_SOURCE } from '../ui/type-ahead/analytics';
5
+ /**
6
+ * Container that renders the recaptcha component from the mention provider and manages handleSuccess.
7
+ * Does NOT pass email - the provider's component uses useInlineInviteRecaptcha hook internally
8
+ * and wires showRecaptcha to the provider. When user clicks invite item, type-ahead calls
9
+ * mentionProvider.showInlineInviteRecaptcha(email) which passes email to the component.
10
+ */
11
+ export const InlineInviteRecaptchaContainer = ({
12
+ mentionProvider,
13
+ api
14
+ }) => {
15
+ var _api$mention2, _api$mention2$command, _api$core2, _api$core2$actions;
16
+ const [provider, setProvider] = useState(null);
17
+ useEffect(() => {
18
+ if (!mentionProvider) {
19
+ return;
20
+ }
21
+ let isMounted = true;
22
+ mentionProvider.then(resolvedProvider => {
23
+ if (!isMounted) {
24
+ return;
25
+ }
26
+ setProvider(resolvedProvider);
27
+ }).catch(() => {
28
+ // Silently handle promise rejection
29
+ });
30
+ return () => {
31
+ isMounted = false;
32
+ setProvider(null);
33
+ };
34
+ }, [mentionProvider]);
35
+ const handleSuccess = useCallback((userId, email) => {
36
+ var _api$mention, _api$mention$commands, _api$core, _api$core$actions;
37
+ if (!(api !== null && api !== void 0 && (_api$mention = api.mention) !== null && _api$mention !== void 0 && (_api$mention$commands = _api$mention.commands) !== null && _api$mention$commands !== void 0 && _api$mention$commands.insertMention) || !(api !== null && api !== void 0 && (_api$core = api.core) !== null && _api$core !== void 0 && (_api$core$actions = _api$core.actions) !== null && _api$core$actions !== void 0 && _api$core$actions.execute)) {
38
+ return;
39
+ }
40
+ const name = email.split('@')[0] || email;
41
+ api.core.actions.execute(api.mention.commands.insertMention({
42
+ id: userId,
43
+ name,
44
+ userType: 'DEFAULT',
45
+ accessLevel: 'CONTAINER'
46
+ }));
47
+ }, [api]);
48
+ const handleClose = useCallback(() => {
49
+ // No-op: recaptcha state is managed by the hook-based component
50
+ }, []);
51
+ const handleReady = useCallback(showRecaptcha => {
52
+ if (provider) {
53
+ if (showRecaptcha) {
54
+ provider.showInlineInviteRecaptcha = showRecaptcha;
55
+ } else {
56
+ delete provider.showInlineInviteRecaptcha;
57
+ }
58
+ }
59
+ }, [provider]);
60
+ if (!(provider !== null && provider !== void 0 && provider.InlineInviteRecaptcha) || !(api !== null && api !== void 0 && (_api$mention2 = api.mention) !== null && _api$mention2 !== void 0 && (_api$mention2$command = _api$mention2.commands) !== null && _api$mention2$command !== void 0 && _api$mention2$command.insertMention) || !(api !== null && api !== void 0 && (_api$core2 = api.core) !== null && _api$core2 !== void 0 && (_api$core2$actions = _api$core2.actions) !== null && _api$core2$actions !== void 0 && _api$core2$actions.execute)) {
61
+ return null;
62
+ }
63
+ const RecaptchaComponent = provider.InlineInviteRecaptcha;
64
+ return /*#__PURE__*/React.createElement(RecaptchaComponent, {
65
+ analyticsSource: MENTION_SOURCE,
66
+ onSuccess: handleSuccess,
67
+ onClose: handleClose,
68
+ onReady: handleReady
69
+ });
70
+ };
@@ -153,7 +153,7 @@ const InviteItemWithEmailDomain = ({
153
153
  };
154
154
  }, [query, isEmailValid]);
155
155
  const displayName = query && emailDomain ? possibleEmail : undefined;
156
- return /*#__PURE__*/React.createElement("div", {
156
+ return displayName && /*#__PURE__*/React.createElement("div", {
157
157
  role: "button",
158
158
  tabIndex: 0,
159
159
  onMouseDown: onSelected,
@@ -175,19 +175,8 @@ const InviteItemWithEmailDomain = ({
175
175
  })), /*#__PURE__*/React.createElement("div", {
176
176
  "data-testid": "name-section",
177
177
  className: ax([style.nameSection])
178
- }, displayName ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, displayName), /*#__PURE__*/React.createElement("div", {
178
+ }, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, displayName), /*#__PURE__*/React.createElement("div", {
179
179
  className: ax([style.byline])
180
- }, getByline())) : /*#__PURE__*/React.createElement(FormattedMessage
181
- // Ignored via go/ees005
182
- // eslint-disable-next-line react/jsx-props-no-spreading
183
- , _extends({}, messages.inviteItemTitle, {
184
- values: {
185
- userRole: userRole || 'basic',
186
- productName: /*#__PURE__*/React.createElement("span", {
187
- "data-testid": "capitalized-message",
188
- className: ax([style.capitalize])
189
- }, productName)
190
- }
191
- })))));
180
+ }, getByline())))));
192
181
  };
193
182
  export default injectIntl(InviteItemWithEmailDomain);
@@ -2,7 +2,7 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
2
2
  import { isSpecialMention } from '@atlaskit/mention/resource';
3
3
  import { isTeamType } from './utils';
4
4
  const componentName = 'mention';
5
- const source = 'mentionInEditor';
5
+ export const MENTION_SOURCE = 'mentionInEditor';
6
6
  const emptyQueryResponse = {
7
7
  queryLength: 0,
8
8
  spaceInQuery: false
@@ -61,7 +61,7 @@ export const buildTypeAheadInviteItemViewedPayload = (sessionId, contextIdentifi
61
61
  childObjectId,
62
62
  userRole,
63
63
  sessionId,
64
- source
64
+ source: MENTION_SOURCE
65
65
  }
66
66
  };
67
67
  };
@@ -332,8 +332,22 @@ export const createTypeAheadConfig = ({
332
332
  if (mentionProvider && mentionProvider.shouldEnableInvite && isInviteItem(item.mention)) {
333
333
  // Don't fire event and the callback with selection by space press
334
334
  if (mode !== 'space') {
335
+ var _mentionProvider$getS2;
335
336
  fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole));
336
- if (mentionProvider.onInviteItemClick) {
337
+ if ((_mentionProvider$getS2 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS2 !== void 0 && _mentionProvider$getS2.call(mentionProvider) && fg('jira_invites_auto_tag_new_user_in_mentions_fg')) {
338
+ // Get the email from query, using the same logic as InviteItemWithEmailDomain
339
+ const emailDomain = mentionProvider.userEmailDomain;
340
+ let email = query || '';
341
+ // If query doesn't include @ and we have an email domain, append it
342
+ if (email && !email.includes('@') && emailDomain) {
343
+ email = `${email.toLowerCase()}@${emailDomain}`;
344
+ }
345
+ // If query already includes @, use it as is
346
+ if (email && mentionProvider.showInlineInviteRecaptcha) {
347
+ mentionProvider.showInlineInviteRecaptcha(email);
348
+ }
349
+ } else if (mentionProvider.onInviteItemClick) {
350
+ // Fallback to old behavior for backward compatibility
337
351
  mentionProvider.onInviteItemClick('mention');
338
352
  }
339
353
  }
@@ -18,6 +18,7 @@ import { insertMention } from './editor-commands';
18
18
  import { mentionNodeSpec } from './nodeviews/mentionNodeSpec';
19
19
  import { mentionPluginKey } from './pm-plugins/key';
20
20
  import { ACTIONS, createMentionPlugin } from './pm-plugins/main';
21
+ import { InlineInviteRecaptchaContainer } from './ui/InlineInviteRecaptchaContainer';
21
22
  import { SecondaryToolbarComponent } from './ui/SecondaryToolbarComponent';
22
23
  import { createTypeAheadConfig } from './ui/type-ahead';
23
24
  var processName = function processName(name, intl) {
@@ -129,10 +130,13 @@ var mentionsPlugin = function mentionsPlugin(_ref3) {
129
130
  providerFactory: providerFactory,
130
131
  renderNode: function renderNode(_ref5) {
131
132
  var mentionProvider = _ref5.mentionProvider;
132
- return /*#__PURE__*/React.createElement(Component, {
133
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Component, {
133
134
  mentionProvider: mentionProvider,
134
135
  api: api
135
- });
136
+ }), fg('jira_invites_auto_tag_new_user_in_mentions_fg') && /*#__PURE__*/React.createElement(InlineInviteRecaptchaContainer, {
137
+ mentionProvider: mentionProvider,
138
+ api: api
139
+ }));
136
140
  }
137
141
  });
138
142
  },
@@ -0,0 +1,73 @@
1
+ /* InlineInviteRecaptchaContainer.tsx generated by @compiled/babel-plugin v0.38.1 */
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import { ax, ix } from "@compiled/react/runtime";
4
+ import React, { useCallback, useEffect, useState } from 'react';
5
+ import { MENTION_SOURCE } from '../ui/type-ahead/analytics';
6
+ /**
7
+ * Container that renders the recaptcha component from the mention provider and manages handleSuccess.
8
+ * Does NOT pass email - the provider's component uses useInlineInviteRecaptcha hook internally
9
+ * and wires showRecaptcha to the provider. When user clicks invite item, type-ahead calls
10
+ * mentionProvider.showInlineInviteRecaptcha(email) which passes email to the component.
11
+ */
12
+ export var InlineInviteRecaptchaContainer = function InlineInviteRecaptchaContainer(_ref) {
13
+ var _api$mention2, _api$core2;
14
+ var mentionProvider = _ref.mentionProvider,
15
+ api = _ref.api;
16
+ var _useState = useState(null),
17
+ _useState2 = _slicedToArray(_useState, 2),
18
+ provider = _useState2[0],
19
+ setProvider = _useState2[1];
20
+ useEffect(function () {
21
+ if (!mentionProvider) {
22
+ return;
23
+ }
24
+ var isMounted = true;
25
+ mentionProvider.then(function (resolvedProvider) {
26
+ if (!isMounted) {
27
+ return;
28
+ }
29
+ setProvider(resolvedProvider);
30
+ }).catch(function () {
31
+ // Silently handle promise rejection
32
+ });
33
+ return function () {
34
+ isMounted = false;
35
+ setProvider(null);
36
+ };
37
+ }, [mentionProvider]);
38
+ var handleSuccess = useCallback(function (userId, email) {
39
+ var _api$mention, _api$core;
40
+ if (!(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) || !(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)) {
41
+ return;
42
+ }
43
+ var name = email.split('@')[0] || email;
44
+ api.core.actions.execute(api.mention.commands.insertMention({
45
+ id: userId,
46
+ name: name,
47
+ userType: 'DEFAULT',
48
+ accessLevel: 'CONTAINER'
49
+ }));
50
+ }, [api]);
51
+ var handleClose = useCallback(function () {
52
+ // No-op: recaptcha state is managed by the hook-based component
53
+ }, []);
54
+ var handleReady = useCallback(function (showRecaptcha) {
55
+ if (provider) {
56
+ if (showRecaptcha) {
57
+ provider.showInlineInviteRecaptcha = showRecaptcha;
58
+ } else {
59
+ delete provider.showInlineInviteRecaptcha;
60
+ }
61
+ }
62
+ }, [provider]);
63
+ if (!(provider !== null && provider !== void 0 && provider.InlineInviteRecaptcha) || !(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$core2 = api.core) !== null && _api$core2 !== void 0 && (_api$core2 = _api$core2.actions) !== null && _api$core2 !== void 0 && _api$core2.execute)) {
64
+ return null;
65
+ }
66
+ var RecaptchaComponent = provider.InlineInviteRecaptcha;
67
+ return /*#__PURE__*/React.createElement(RecaptchaComponent, {
68
+ analyticsSource: MENTION_SOURCE,
69
+ onSuccess: handleSuccess,
70
+ onClose: handleClose,
71
+ onReady: handleReady
72
+ });
73
+ };
@@ -157,7 +157,7 @@ var InviteItemWithEmailDomain = function InviteItemWithEmailDomain(_ref) {
157
157
  };
158
158
  }, [query, isEmailValid]);
159
159
  var displayName = query && emailDomain ? possibleEmail : undefined;
160
- return /*#__PURE__*/React.createElement("div", {
160
+ return displayName && /*#__PURE__*/React.createElement("div", {
161
161
  role: "button",
162
162
  tabIndex: 0,
163
163
  onMouseDown: onSelected,
@@ -182,19 +182,8 @@ var InviteItemWithEmailDomain = function InviteItemWithEmailDomain(_ref) {
182
182
  })), /*#__PURE__*/React.createElement("div", {
183
183
  "data-testid": "name-section",
184
184
  className: ax([style.nameSection])
185
- }, displayName ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, displayName), /*#__PURE__*/React.createElement("div", {
185
+ }, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, displayName), /*#__PURE__*/React.createElement("div", {
186
186
  className: ax([style.byline])
187
- }, getByline())) : /*#__PURE__*/React.createElement(FormattedMessage
188
- // Ignored via go/ees005
189
- // eslint-disable-next-line react/jsx-props-no-spreading
190
- , _extends({}, messages.inviteItemTitle, {
191
- values: {
192
- userRole: userRole || 'basic',
193
- productName: /*#__PURE__*/React.createElement("span", {
194
- "data-testid": "capitalized-message",
195
- className: ax([style.capitalize])
196
- }, productName)
197
- }
198
- })))));
187
+ }, getByline())))));
199
188
  };
200
189
  export default injectIntl(InviteItemWithEmailDomain);
@@ -2,7 +2,7 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
2
2
  import { isSpecialMention } from '@atlaskit/mention/resource';
3
3
  import { isTeamType } from './utils';
4
4
  var componentName = 'mention';
5
- var source = 'mentionInEditor';
5
+ export var MENTION_SOURCE = 'mentionInEditor';
6
6
  var emptyQueryResponse = {
7
7
  queryLength: 0,
8
8
  spaceInQuery: false
@@ -63,7 +63,7 @@ export var buildTypeAheadInviteItemViewedPayload = function buildTypeAheadInvite
63
63
  childObjectId: childObjectId,
64
64
  userRole: userRole,
65
65
  sessionId: sessionId,
66
- source: source
66
+ source: MENTION_SOURCE
67
67
  }
68
68
  };
69
69
  };
@@ -334,8 +334,22 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref6) {
334
334
  if (mentionProvider && mentionProvider.shouldEnableInvite && isInviteItem(item.mention)) {
335
335
  // Don't fire event and the callback with selection by space press
336
336
  if (mode !== 'space') {
337
+ var _mentionProvider$getS2;
337
338
  fireEvent(buildTypeAheadInviteItemClickedPayload(pickerElapsedTime, stats.keyCount.arrowUp, stats.keyCount.arrowDown, sessionId, mode, query, contextIdentifierProvider, mentionProvider.userRole));
338
- if (mentionProvider.onInviteItemClick) {
339
+ if ((_mentionProvider$getS2 = mentionProvider.getShouldEnableInlineInvite) !== null && _mentionProvider$getS2 !== void 0 && _mentionProvider$getS2.call(mentionProvider) && fg('jira_invites_auto_tag_new_user_in_mentions_fg')) {
340
+ // Get the email from query, using the same logic as InviteItemWithEmailDomain
341
+ var emailDomain = mentionProvider.userEmailDomain;
342
+ var email = query || '';
343
+ // If query doesn't include @ and we have an email domain, append it
344
+ if (email && !email.includes('@') && emailDomain) {
345
+ email = "".concat(email.toLowerCase(), "@").concat(emailDomain);
346
+ }
347
+ // If query already includes @, use it as is
348
+ if (email && mentionProvider.showInlineInviteRecaptcha) {
349
+ mentionProvider.showInlineInviteRecaptcha(email);
350
+ }
351
+ } else if (mentionProvider.onInviteItemClick) {
352
+ // Fallback to old behavior for backward compatibility
339
353
  mentionProvider.onInviteItemClick('mention');
340
354
  }
341
355
  }
@@ -0,0 +1,15 @@
1
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { MentionProvider } from '@atlaskit/mention/resource';
3
+ import type { MentionsPlugin } from '../mentionsPluginType';
4
+ interface Props {
5
+ api: ExtractInjectionAPI<MentionsPlugin> | undefined;
6
+ mentionProvider: Promise<MentionProvider> | undefined;
7
+ }
8
+ /**
9
+ * Container that renders the recaptcha component from the mention provider and manages handleSuccess.
10
+ * Does NOT pass email - the provider's component uses useInlineInviteRecaptcha hook internally
11
+ * and wires showRecaptcha to the provider. When user clicks invite item, type-ahead calls
12
+ * mentionProvider.showInlineInviteRecaptcha(email) which passes email to the component.
13
+ */
14
+ export declare const InlineInviteRecaptchaContainer: ({ mentionProvider, api, }: Props) => JSX.Element | null;
15
+ export {};
@@ -4,6 +4,7 @@ import type { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
4
4
  import type { UserRole } from '@atlaskit/mention';
5
5
  import type { MentionDescription } from '@atlaskit/mention/resource';
6
6
  import type { TeamInfoAttrAnalytics } from '../../types';
7
+ export declare const MENTION_SOURCE = "mentionInEditor";
7
8
  export declare const buildTypeAheadCancelPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, query?: string) => AnalyticsEventPayload;
8
9
  export declare const buildTypeAheadInviteItemViewedPayload: (sessionId: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole) => AnalyticsEventPayload;
9
10
  export declare const buildTypeAheadInviteItemClickedPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, insertType: SelectItemMode, query?: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole) => AnalyticsEventPayload;
@@ -0,0 +1,15 @@
1
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { MentionProvider } from '@atlaskit/mention/resource';
3
+ import type { MentionsPlugin } from '../mentionsPluginType';
4
+ interface Props {
5
+ api: ExtractInjectionAPI<MentionsPlugin> | undefined;
6
+ mentionProvider: Promise<MentionProvider> | undefined;
7
+ }
8
+ /**
9
+ * Container that renders the recaptcha component from the mention provider and manages handleSuccess.
10
+ * Does NOT pass email - the provider's component uses useInlineInviteRecaptcha hook internally
11
+ * and wires showRecaptcha to the provider. When user clicks invite item, type-ahead calls
12
+ * mentionProvider.showInlineInviteRecaptcha(email) which passes email to the component.
13
+ */
14
+ export declare const InlineInviteRecaptchaContainer: ({ mentionProvider, api, }: Props) => JSX.Element | null;
15
+ export {};
@@ -4,6 +4,7 @@ import type { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
4
4
  import type { UserRole } from '@atlaskit/mention';
5
5
  import type { MentionDescription } from '@atlaskit/mention/resource';
6
6
  import type { TeamInfoAttrAnalytics } from '../../types';
7
+ export declare const MENTION_SOURCE = "mentionInEditor";
7
8
  export declare const buildTypeAheadCancelPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, query?: string) => AnalyticsEventPayload;
8
9
  export declare const buildTypeAheadInviteItemViewedPayload: (sessionId: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole) => AnalyticsEventPayload;
9
10
  export declare const buildTypeAheadInviteItemClickedPayload: (duration: number, upKeyCount: number, downKeyCount: number, sessionId: string, insertType: SelectItemMode, query?: string, contextIdentifierProvider?: ContextIdentifierProvider, userRole?: UserRole) => AnalyticsEventPayload;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-mentions",
3
- "version": "9.1.8",
3
+ "version": "9.2.0",
4
4
  "description": "Mentions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -45,9 +45,9 @@
45
45
  "@atlaskit/popper": "^7.1.0",
46
46
  "@atlaskit/portal": "^5.2.0",
47
47
  "@atlaskit/primitives": "^18.0.0",
48
- "@atlaskit/profilecard": "^24.34.0",
48
+ "@atlaskit/profilecard": "^24.35.0",
49
49
  "@atlaskit/theme": "^21.0.0",
50
- "@atlaskit/tmp-editor-statsig": "^21.0.0",
50
+ "@atlaskit/tmp-editor-statsig": "^22.3.0",
51
51
  "@atlaskit/tokens": "^11.0.0",
52
52
  "@atlaskit/user-picker": "^11.21.0",
53
53
  "@babel/runtime": "^7.0.0",