@atlaskit/editor-plugin-mentions
Version:
Mentions plugin for @atlaskit/editor-core
218 lines (216 loc) • 9.52 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
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 { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
import { insm } from '@atlaskit/insm';
import { SLI_EVENT_TYPE, SMART_EVENT_TYPE } from '@atlaskit/mention/resource';
import { ComponentNames } from '@atlaskit/mention/types';
import { fg } from '@atlaskit/platform-feature-flags';
import { MentionNodeView } from '../nodeviews/mentionNodeView';
import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types';
import { mentionPluginKey } from './key';
import { canMentionBeCreatedInRange } from './utils';
export var ACTIONS = {
SET_PROVIDER: 'SET_PROVIDER'
};
var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
var PACKAGE_VERSION = "12.1.4";
var setProvider = function setProvider(provider) {
return function (state, dispatch) {
if (dispatch) {
dispatch(state.tr.setMeta(mentionPluginKey, {
action: ACTIONS.SET_PROVIDER,
params: {
provider: provider
}
}));
}
return true;
};
};
export function createMentionPlugin(_ref) {
var pmPluginFactoryParams = _ref.pmPluginFactoryParams,
fireEvent = _ref.fireEvent,
options = _ref.options,
api = _ref.api;
var mentionProvider;
var sendAnalytics = function sendAnalytics(event, actionSubject, action, attributes) {
if (event === SLI_EVENT_TYPE || event === SMART_EVENT_TYPE) {
fireEvent({
action: action,
actionSubject: actionSubject,
eventType: EVENT_TYPE.OPERATIONAL,
attributes: _objectSpread({
packageName: PACKAGE_NAME,
packageVersion: PACKAGE_VERSION,
componentName: ComponentNames.MENTION
}, attributes)
}, 'fabricElements');
}
};
return new SafePlugin({
key: mentionPluginKey,
state: {
init: function init(_, state) {
var canInsertMention = canMentionBeCreatedInRange(state.selection.from, state.selection.to)(state);
return {
canInsertMention: canInsertMention
};
},
apply: function apply(tr, pluginState, oldState, newState) {
var _ref2 = tr.getMeta(mentionPluginKey) || {
action: null,
params: null
},
action = _ref2.action,
params = _ref2.params;
var hasNewPluginState = false;
var newPluginState = pluginState;
var hasPositionChanged = oldState.selection.from !== newState.selection.from || oldState.selection.to !== newState.selection.to;
if (tr.docChanged || tr.selectionSet && hasPositionChanged) {
newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
canInsertMention: canMentionBeCreatedInRange(newState.selection.from, newState.selection.to)(newState)
});
hasNewPluginState = true;
}
switch (action) {
case ACTIONS.SET_PROVIDER:
newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
mentionProvider: params.provider
});
hasNewPluginState = true;
break;
}
if (hasNewPluginState) {
pmPluginFactoryParams.dispatch(mentionPluginKey, newPluginState);
}
if (options !== null && options !== void 0 && options.handleMentionsChanged && tr.docChanged) {
var _insm$session, _insm$session2;
(_insm$session = insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('mentionDeletionDetection');
var mentionSchema = newState.schema.nodes.mention;
var mentionsRemoved = new Map();
tr.steps.forEach(function (step, index) {
step.getMap().forEach(function (from, to) {
var newStart = tr.mapping.slice(index).map(from, -1);
var newEnd = tr.mapping.slice(index).map(to);
var oldStart = tr.mapping.invert().map(newStart, -1);
var oldEnd = tr.mapping.invert().map(newEnd);
var oldSlice = oldState.doc.slice(oldStart, oldEnd);
var newSlice = newState.doc.slice(newStart, newEnd);
var mentionsBefore = new Map();
var mentionsAfter = new Map();
oldSlice.content.descendants(function (node) {
if (node.type.name === mentionSchema.name && node.attrs.localId) {
mentionsBefore.set(node.attrs.localId, {
id: node.attrs.id,
localId: node.attrs.localId
});
}
});
newSlice.content.descendants(function (node) {
if (node.type.name === mentionSchema.name && node.attrs.localId) {
mentionsAfter.set(node.attrs.localId, {
id: node.attrs.id,
localId: node.attrs.localId
});
}
});
// Determine which mentions were removed in this step
mentionsBefore.forEach(function (mention, localId) {
if (!mentionsAfter.has(localId)) {
mentionsRemoved.set(localId, mention);
}
});
// Adjust mentionsRemoved by removing any that reappear
mentionsAfter.forEach(function (_, localId) {
if (mentionsRemoved.has(localId)) {
mentionsRemoved.delete(localId);
}
});
});
});
if (mentionsRemoved.size > 0) {
var changes = Array.from(mentionsRemoved.values()).map(function (mention) {
return {
id: mention.id,
localId: mention.localId,
type: 'deleted'
};
});
options.handleMentionsChanged(changes);
}
(_insm$session2 = insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('mentionDeletionDetection');
}
return newPluginState;
}
},
props: {
nodeViews: {
mention: function mention(node) {
return new MentionNodeView(node, {
options: options,
api: api,
portalProviderAPI: pmPluginFactoryParams.portalProviderAPI
});
}
}
},
view: function view(editorView) {
var providerHandler = function providerHandler(name, providerPromise) {
switch (name) {
case 'mentionProvider':
if (!providerPromise) {
fireEvent({
action: ACTION.ERRORED,
actionSubject: ACTION_SUBJECT.MENTION,
actionSubjectId: ACTION_SUBJECT_ID.MENTION_PROVIDER,
eventType: EVENT_TYPE.OPERATIONAL,
attributes: {
reason: MENTION_PROVIDER_UNDEFINED
}
});
return setProvider(undefined)(editorView.state, editorView.dispatch);
}
providerPromise.then(function (provider) {
if (mentionProvider) {
mentionProvider.unsubscribe('mentionPlugin');
}
mentionProvider = provider;
setProvider(provider)(editorView.state, editorView.dispatch);
provider.subscribe('mentionPlugin', undefined, undefined, undefined, undefined, sendAnalytics);
}).catch(function () {
fireEvent({
action: ACTION.ERRORED,
actionSubject: ACTION_SUBJECT.MENTION,
actionSubjectId: ACTION_SUBJECT_ID.MENTION_PROVIDER,
eventType: EVENT_TYPE.OPERATIONAL,
attributes: {
reason: MENTION_PROVIDER_REJECTED
}
});
return setProvider(undefined)(editorView.state, editorView.dispatch);
});
break;
}
return;
};
var providerViaConfig = fg('platform_editor_mention_provider_via_plugin_config');
if (providerViaConfig && options !== null && options !== void 0 && options.mentionProvider) {
providerHandler('mentionProvider', options === null || options === void 0 ? void 0 : options.mentionProvider);
} else {
pmPluginFactoryParams.providerFactory.subscribe('mentionProvider', providerHandler);
}
return {
destroy: function destroy() {
if (pmPluginFactoryParams.providerFactory) {
pmPluginFactoryParams.providerFactory.unsubscribe('mentionProvider', providerHandler);
}
if (mentionProvider) {
mentionProvider.unsubscribe('mentionPlugin');
}
}
};
}
});
}