@atlaskit/editor-plugin-mentions
Version:
Mentions plugin for @atlaskit/editor-core
276 lines (275 loc) • 12.5 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import _regeneratorRuntime from "@babel/runtime/regenerator";
import React, { useEffect, useMemo } from 'react';
import { useIntl } from 'react-intl';
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
import uuid from 'uuid';
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
import { toolbarInsertBlockMessages as messages, mentionMessages } from '@atlaskit/editor-common/messages';
import { WithProviders } from '@atlaskit/editor-common/provider-factory';
import { IconMention } from '@atlaskit/editor-common/quick-insert';
import { isResolvingMentionProvider } from '@atlaskit/mention/resource';
import { MentionNameStatus, isPromise } from '@atlaskit/mention/types';
import { fg } from '@atlaskit/platform-feature-flags';
import { insertMention } from './editor-commands';
import { mentionNodeSpec } from './nodeviews/mentionNodeSpec';
import { mentionPluginKey } from './pm-plugins/key';
import { ACTIONS, createMentionPlugin } from './pm-plugins/main';
import { createMentionPlaceholderPlugin } from './pm-plugins/mentionPlaceholder';
import { InlineInviteRecaptchaContainer } from './ui/InlineInviteRecaptchaContainer';
import { SecondaryToolbarComponent } from './ui/SecondaryToolbarComponent';
import { createTypeAheadConfig } from './ui/type-ahead';
var processName = function processName(name, intl) {
var unknownLabel = intl.formatMessage(mentionMessages.unknownLabel);
if (name.status === MentionNameStatus.OK) {
return "@".concat(name.name || unknownLabel);
} else {
return "@".concat(unknownLabel);
}
};
/**
* We will need to clean this up once mentionProvider is
* put inside mention plugin.
* See: https://product-fabric.atlassian.net/browse/ED-26011
*/
function Component(_ref) {
var mentionProvider = _ref.mentionProvider,
api = _ref.api;
var mentionProviderMemo = useMemo(function () {
return mentionProvider;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
var intl = useIntl();
useEffect(function () {
mentionProviderMemo === null || mentionProviderMemo === void 0 || mentionProviderMemo.then(function (mentionProviderSync) {
var _api$base;
api === null || api === void 0 || (_api$base = api.base) === null || _api$base === void 0 || (_api$base = _api$base.actions) === null || _api$base === void 0 || _api$base.registerMarks(function (_ref2) {
var tr = _ref2.tr,
node = _ref2.node,
pos = _ref2.pos;
var doc = tr.doc;
var schema = doc.type.schema;
var mentionNodeType = schema.nodes.mention;
var id = node.attrs.id;
if (node.type === mentionNodeType) {
if (isResolvingMentionProvider(mentionProviderSync)) {
var nameDetail = mentionProviderSync === null || mentionProviderSync === void 0 ? void 0 : mentionProviderSync.resolveMentionName(id);
var newText;
if (isPromise(nameDetail)) {
newText = "@".concat(intl.formatMessage(mentionMessages.unknownLabel));
} else {
newText = processName(nameDetail, intl);
}
var currentPos = tr.mapping.map(pos);
tr.replaceWith(currentPos, currentPos + node.nodeSize, schema.text(newText, node.marks));
}
}
});
});
}, [mentionProviderMemo, api, intl]);
return null;
}
var mentionsPlugin = function mentionsPlugin(_ref3) {
var _options$sanitizePriv, _options$insertDispla;
var options = _ref3.config,
api = _ref3.api;
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
var sessionId = uuid();
var previousMediaProvider;
var fireEvent = function fireEvent(payload, channel) {
var _api$analytics;
var fireAnalyticsEvent = api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 ? void 0 : _api$analytics.fireAnalyticsEvent;
if (!fireAnalyticsEvent) {
return;
}
if (payload.attributes && !payload.attributes.sessionId) {
payload.attributes.sessionId = sessionId;
}
fireAnalyticsEvent(payload, channel);
};
var typeAhead = createTypeAheadConfig({
sanitizePrivateContent: options === null || options === void 0 ? void 0 : options.sanitizePrivateContent,
mentionInsertDisplayName: options === null || options === void 0 ? void 0 : options.insertDisplayName,
HighlightComponent: options === null || options === void 0 ? void 0 : options.HighlightComponent,
handleMentionsChanged: options === null || options === void 0 ? void 0 : options.handleMentionsChanged,
fireEvent: fireEvent,
api: api
});
return {
name: 'mention',
nodes: function nodes() {
return [{
name: 'mention',
node: mentionNodeSpec()
}];
},
pmPlugins: function pmPlugins() {
var plugins = [{
name: 'mention',
plugin: function plugin(pmPluginFactoryParams) {
return createMentionPlugin({
pmPluginFactoryParams: pmPluginFactoryParams,
fireEvent: fireEvent,
options: options,
api: api
});
}
}];
if (fg('jira_invites_auto_tag_new_user_in_mentions_fg')) {
plugins.push({
name: 'mentionPlaceholder',
plugin: function plugin() {
return createMentionPlaceholderPlugin();
}
});
}
return plugins;
},
contentComponent: function contentComponent(_ref4) {
var editorView = _ref4.editorView,
providerFactory = _ref4.providerFactory;
if (!editorView) {
return null;
}
return /*#__PURE__*/React.createElement(WithProviders
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
, {
providers: ['mentionProvider'],
providerFactory: providerFactory
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
renderNode: function renderNode(_ref5) {
var mentionProvider = _ref5.mentionProvider;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Component, {
mentionProvider: mentionProvider,
api: api
}), fg('jira_invites_auto_tag_new_user_in_mentions_fg') && /*#__PURE__*/React.createElement(InlineInviteRecaptchaContainer, {
mentionProvider: mentionProvider,
api: api
}));
}
});
},
secondaryToolbarComponent: function secondaryToolbarComponent(_ref6) {
var editorView = _ref6.editorView,
disabled = _ref6.disabled;
if (!editorView) {
return null;
}
return /*#__PURE__*/React.createElement(SecondaryToolbarComponent, {
editorView: editorView,
api: api,
disabled: disabled,
typeAhead: typeAhead
});
},
commands: {
insertMention: insertMention({
sanitizePrivateContent: (_options$sanitizePriv = options === null || options === void 0 ? void 0 : options.sanitizePrivateContent) !== null && _options$sanitizePriv !== void 0 ? _options$sanitizePriv : false,
mentionInsertDisplayName: (_options$insertDispla = options === null || options === void 0 ? void 0 : options.insertDisplayName) !== null && _options$insertDispla !== void 0 ? _options$insertDispla : false,
api: api
})
},
actions: {
openTypeAhead: function openTypeAhead(inputMethod) {
var _api$typeAhead;
return Boolean(api === null || api === void 0 || (_api$typeAhead = api.typeAhead) === null || _api$typeAhead === void 0 || (_api$typeAhead = _api$typeAhead.actions) === null || _api$typeAhead === void 0 ? void 0 : _api$typeAhead.open({
triggerHandler: typeAhead,
inputMethod: inputMethod
}));
},
announceMentionsInsertion: function announceMentionsInsertion(mentionChanges) {
if (options !== null && options !== void 0 && options.handleMentionsChanged) {
options.handleMentionsChanged(mentionChanges);
}
},
setProvider: function () {
var _setProvider = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(providerPromise) {
var _api$core$actions$exe;
var provider;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (fg('platform_editor_mention_provider_via_plugin_config')) {
_context.next = 2;
break;
}
return _context.abrupt("return", false);
case 2:
_context.next = 4;
return providerPromise;
case 4:
provider = _context.sent;
if (!(previousMediaProvider === provider)) {
_context.next = 7;
break;
}
return _context.abrupt("return", false);
case 7:
previousMediaProvider = provider;
return _context.abrupt("return", (_api$core$actions$exe = api === null || api === void 0 ? void 0 : api.core.actions.execute(function (_ref7) {
var tr = _ref7.tr;
return tr.setMeta(mentionPluginKey, {
action: ACTIONS.SET_PROVIDER,
params: {
provider: provider
}
});
})) !== null && _api$core$actions$exe !== void 0 ? _api$core$actions$exe : false);
case 9:
case "end":
return _context.stop();
}
}, _callee);
}));
function setProvider(_x) {
return _setProvider.apply(this, arguments);
}
return setProvider;
}()
},
getSharedState: function getSharedState(editorState) {
if (!editorState) {
return undefined;
}
var mentionPluginState = mentionPluginKey.getState(editorState);
return _objectSpread(_objectSpread({}, mentionPluginState), {}, {
typeAheadHandler: typeAhead
});
},
pluginsOptions: {
quickInsert: function quickInsert(_ref8) {
var formatMessage = _ref8.formatMessage;
return [{
id: 'mention',
title: formatMessage(messages.mention),
description: formatMessage(messages.mentionDescription),
keywords: ['team', 'user'],
priority: 400,
keyshortcut: '@',
icon: function icon() {
return /*#__PURE__*/React.createElement(IconMention, null);
},
action: function action(insert, state) {
var _api$typeAhead2;
var tr = insert(undefined);
var pluginState = mentionPluginKey.getState(state);
if (pluginState && pluginState.canInsertMention === false) {
return false;
}
api === null || api === void 0 || (_api$typeAhead2 = api.typeAhead) === null || _api$typeAhead2 === void 0 || _api$typeAhead2.actions.openAtTransaction({
triggerHandler: typeAhead,
inputMethod: INPUT_METHOD.QUICK_INSERT
})(tr);
return tr;
}
}];
},
typeAhead: typeAhead
}
};
};
export { mentionsPlugin };