@atlaskit/editor-plugin-mentions 9.1.9 → 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 +11 -0
- package/dist/cjs/mentionsPlugin.js +6 -2
- package/dist/cjs/ui/InlineInviteRecaptchaContainer.js +82 -0
- package/dist/cjs/ui/InviteItem/InviteItemWithEmailDomain.js +3 -14
- package/dist/cjs/ui/type-ahead/analytics.js +3 -3
- package/dist/cjs/ui/type-ahead/index.js +15 -1
- package/dist/es2019/mentionsPlugin.js +6 -2
- package/dist/es2019/ui/InlineInviteRecaptchaContainer.js +70 -0
- package/dist/es2019/ui/InviteItem/InviteItemWithEmailDomain.js +3 -14
- package/dist/es2019/ui/type-ahead/analytics.js +2 -2
- package/dist/es2019/ui/type-ahead/index.js +15 -1
- package/dist/esm/mentionsPlugin.js +6 -2
- package/dist/esm/ui/InlineInviteRecaptchaContainer.js +73 -0
- package/dist/esm/ui/InviteItem/InviteItemWithEmailDomain.js +3 -14
- package/dist/esm/ui/type-ahead/analytics.js +2 -2
- package/dist/esm/ui/type-ahead/index.js +15 -1
- package/dist/types/ui/InlineInviteRecaptchaContainer.d.ts +15 -0
- package/dist/types/ui/type-ahead/analytics.d.ts +1 -0
- package/dist/types-ts4.5/ui/InlineInviteRecaptchaContainer.d.ts +15 -0
- package/dist/types-ts4.5/ui/type-ahead/analytics.d.ts +1 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
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
|
+
|
|
3
14
|
## 9.1.9
|
|
4
15
|
|
|
5
16
|
### 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
|
-
},
|
|
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()))
|
|
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
|
|
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:
|
|
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.
|
|
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
|
-
},
|
|
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()))
|
|
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
|
|
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.
|
|
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
|
-
},
|
|
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()))
|
|
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
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
48
|
+
"@atlaskit/profilecard": "^24.35.0",
|
|
49
49
|
"@atlaskit/theme": "^21.0.0",
|
|
50
|
-
"@atlaskit/tmp-editor-statsig": "^22.
|
|
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",
|