@atlaskit/editor-plugin-mentions 4.2.0 → 4.3.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.
@@ -0,0 +1,139 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { browser } from '@atlaskit/editor-common/browser';
3
+ import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
4
+ import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
5
+ import { isResolvingMentionProvider, MentionNameStatus } from '@atlaskit/mention/resource';
6
+ import { isRestricted } from '@atlaskit/mention/types';
7
+ import { profileCardRenderer } from './profileCardRenderer';
8
+ const primitiveClassName = 'editor-mention-primitive';
9
+ const toDOM = node => {
10
+ // packages/elements/mention/src/components/Mention/index.tsx
11
+ const mentionAttrs = {
12
+ contenteditable: 'false',
13
+ 'data-access-level': node.attrs.accessLevel,
14
+ 'data-mention-id': node.attrs.id,
15
+ 'data-prosemirror-content-type': 'node',
16
+ 'data-prosemirror-node-inline': 'true',
17
+ 'data-prosemirror-node-name': 'mention',
18
+ 'data-prosemirror-node-view-type': 'vanilla',
19
+ class: 'mentionView-content-wrap inlineNodeView'
20
+ };
21
+ return ['span', mentionAttrs, ['span', {
22
+ class: 'zeroWidthSpaceContainer'
23
+ }, ['span', {
24
+ class: 'inlineNodeViewAddZeroWidthSpace'
25
+ }, ZERO_WIDTH_SPACE]], ['span', {
26
+ spellcheck: 'false',
27
+ class: primitiveClassName
28
+ }, node.attrs.text || '@…'], browser.android ? ['span', {
29
+ class: 'zeroWidthSpaceContainer',
30
+ contenteditable: 'false'
31
+ }, ['span', {
32
+ class: 'inlineNodeViewAddZeroWidthSpace'
33
+ }, ZERO_WIDTH_SPACE]] : ['span', {
34
+ class: 'inlineNodeViewAddZeroWidthSpace'
35
+ }, ZERO_WIDTH_SPACE]];
36
+ };
37
+ const processName = name => {
38
+ return name.status === MentionNameStatus.OK ? `@${name.name || ''}` : `@_|unknown|_`;
39
+ };
40
+ const handleProviderName = async (mentionProvider, node) => {
41
+ if (isResolvingMentionProvider(mentionProvider) && node.attrs.id && !node.attrs.text) {
42
+ const nameDetail = mentionProvider === null || mentionProvider === void 0 ? void 0 : mentionProvider.resolveMentionName(node.attrs.id);
43
+ const resolvedNameDetail = await nameDetail;
44
+ return processName(resolvedNameDetail);
45
+ }
46
+ };
47
+ const getNewState = (isHighlighted, isRestricted) => {
48
+ if (isHighlighted) {
49
+ return 'self';
50
+ }
51
+ if (isRestricted) {
52
+ return 'restricted';
53
+ }
54
+ return 'default';
55
+ };
56
+ class MentionNodeView {
57
+ constructor(node, config) {
58
+ var _api$mention$sharedSt;
59
+ _defineProperty(this, "state", 'default');
60
+ const {
61
+ options,
62
+ api,
63
+ portalProviderAPI
64
+ } = config;
65
+ const {
66
+ dom,
67
+ contentDOM
68
+ } = DOMSerializer.renderSpec(document, toDOM(node));
69
+ this.dom = dom;
70
+ this.contentDOM = contentDOM;
71
+ this.config = config;
72
+ this.node = node;
73
+ const {
74
+ mentionProvider
75
+ } = (_api$mention$sharedSt = api === null || api === void 0 ? void 0 : api.mention.sharedState.currentState()) !== null && _api$mention$sharedSt !== void 0 ? _api$mention$sharedSt : {};
76
+ this.updateState(mentionProvider);
77
+ this.cleanup = api === null || api === void 0 ? void 0 : api.mention.sharedState.onChange(({
78
+ nextSharedState
79
+ }) => {
80
+ this.updateState(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.mentionProvider);
81
+ });
82
+ const {
83
+ destroyProfileCard,
84
+ removeProfileCard
85
+ } = profileCardRenderer({
86
+ dom,
87
+ options,
88
+ portalProviderAPI,
89
+ node,
90
+ api
91
+ });
92
+ this.destroyProfileCard = destroyProfileCard;
93
+ this.removeProfileCard = removeProfileCard;
94
+ }
95
+ setClassList(state) {
96
+ const mentionElement = this.getMentionPrimitive();
97
+ mentionElement === null || mentionElement === void 0 ? void 0 : mentionElement.classList.toggle('mention-self', state === 'self');
98
+ mentionElement === null || mentionElement === void 0 ? void 0 : mentionElement.classList.toggle('mention-restricted', state === 'restricted');
99
+ }
100
+ getMentionPrimitive() {
101
+ var _this$dom$querySelect;
102
+ return this.dom instanceof HTMLElement ? (_this$dom$querySelect = this.dom.querySelector(`.${primitiveClassName}`)) !== null && _this$dom$querySelect !== void 0 ? _this$dom$querySelect : undefined : undefined;
103
+ }
104
+ setTextContent(name) {
105
+ var _this$config$options;
106
+ if (!(this.dom instanceof HTMLElement)) {
107
+ return;
108
+ }
109
+ const mentionPrimitive = this.getMentionPrimitive();
110
+ if (mentionPrimitive && name && !this.node.attrs.text && (_this$config$options = this.config.options) !== null && _this$config$options !== void 0 && _this$config$options.sanitizePrivateContent) {
111
+ mentionPrimitive.textContent = name;
112
+ }
113
+ }
114
+ async updateState(mentionProvider) {
115
+ var _mentionProvider$shou;
116
+ const isHighlighted = (_mentionProvider$shou = mentionProvider === null || mentionProvider === void 0 ? void 0 : mentionProvider.shouldHighlightMention({
117
+ id: this.node.attrs.id
118
+ })) !== null && _mentionProvider$shou !== void 0 ? _mentionProvider$shou : false;
119
+ const newState = getNewState(isHighlighted, isRestricted(this.node.attrs.accessLevel));
120
+ if (newState !== this.state) {
121
+ this.setClassList(newState);
122
+ this.state = newState;
123
+ }
124
+ const name = await handleProviderName(mentionProvider, this.node);
125
+ this.setTextContent(name);
126
+ }
127
+ destroy() {
128
+ var _this$cleanup, _this$destroyProfileC;
129
+ (_this$cleanup = this.cleanup) === null || _this$cleanup === void 0 ? void 0 : _this$cleanup.call(this);
130
+ (_this$destroyProfileC = this.destroyProfileCard) === null || _this$destroyProfileC === void 0 ? void 0 : _this$destroyProfileC.call(this);
131
+ }
132
+ deselectNode() {
133
+ var _this$removeProfileCa;
134
+ (_this$removeProfileCa = this.removeProfileCard) === null || _this$removeProfileCa === void 0 ? void 0 : _this$removeProfileCa.call(this);
135
+ }
136
+ }
137
+ export const mentionNodeView = config => node => {
138
+ return new MentionNodeView(node, config);
139
+ };
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { bind } from 'bind-event-listener';
3
+ import uuid from 'uuid/v4';
4
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
+ import { ProfileCardComponent } from '../ui/ProfileCardComponent';
6
+ export const profileCardRenderer = ({
7
+ dom,
8
+ options,
9
+ portalProviderAPI,
10
+ node,
11
+ api
12
+ }) => {
13
+ let renderingProfileCard = false;
14
+ const key = uuid();
15
+ let cleanupSelection;
16
+ const removeProfileCard = () => {
17
+ var _cleanupSelection;
18
+ portalProviderAPI.remove(key);
19
+ renderingProfileCard = false;
20
+ (_cleanupSelection = cleanupSelection) === null || _cleanupSelection === void 0 ? void 0 : _cleanupSelection();
21
+ };
22
+ const listenerCleanup = bind(dom, {
23
+ type: 'click',
24
+ listener: () => {
25
+ if (dom instanceof HTMLElement && options !== null && options !== void 0 && options.profilecardProvider && !renderingProfileCard) {
26
+ var _api$selection;
27
+ renderingProfileCard = true;
28
+ portalProviderAPI.render(() => /*#__PURE__*/React.createElement(ProfileCardComponent, {
29
+ activeMention: node,
30
+ profilecardProvider: options === null || options === void 0 ? void 0 : options.profilecardProvider,
31
+ dom: dom,
32
+ closeComponent: removeProfileCard
33
+ }), dom, key);
34
+ // If we change the selection we should also remove the profile card. The "deselectNode"
35
+ // should usually catch this, but it's possible (ie. on triple click) for this not to be called
36
+ // which means the profile card gets stuck open until you click + change selection
37
+ cleanupSelection = api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.sharedState.onChange(({
38
+ nextSharedState
39
+ }) => {
40
+ const selection = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.selection;
41
+ if (selection instanceof NodeSelection ? selection.node === node : false) {
42
+ return;
43
+ }
44
+ removeProfileCard === null || removeProfileCard === void 0 ? void 0 : removeProfileCard();
45
+ });
46
+ }
47
+ }
48
+ });
49
+ return {
50
+ destroyProfileCard: () => {
51
+ listenerCleanup();
52
+ removeProfileCard === null || removeProfileCard === void 0 ? void 0 : removeProfileCard();
53
+ },
54
+ removeProfileCard
55
+ };
56
+ };
@@ -5,7 +5,9 @@ import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
5
5
  import { SLI_EVENT_TYPE, SMART_EVENT_TYPE } from '@atlaskit/mention/resource';
6
6
  import { ComponentNames } from '@atlaskit/mention/types';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
8
9
  import { MentionNodeView } from '../nodeviews/mention';
10
+ import { mentionNodeView } from '../nodeviews/mentionNodeView';
9
11
  import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types';
10
12
  import { mentionPluginKey } from './key';
11
13
  import { canMentionBeCreatedInRange } from './utils';
@@ -13,7 +15,7 @@ export const ACTIONS = {
13
15
  SET_PROVIDER: 'SET_PROVIDER'
14
16
  };
15
17
  const PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
16
- const PACKAGE_VERSION = "4.2.0";
18
+ const PACKAGE_VERSION = "4.3.0";
17
19
  const setProvider = provider => (state, dispatch) => {
18
20
  if (dispatch) {
19
21
  dispatch(state.tr.setMeta(mentionPluginKey, {
@@ -91,15 +93,21 @@ export function createMentionPlugin({
91
93
  },
92
94
  props: {
93
95
  nodeViews: {
94
- mention: getInlineNodeViewProducer({
95
- pmPluginFactoryParams,
96
- Component: MentionNodeView,
97
- extraComponentProps: {
98
- providerFactory: pmPluginFactoryParams.providerFactory,
99
- pluginInjectionApi: api,
100
- options
101
- }
102
- })
96
+ mention: (node, view, getPos, decorations, innerDecorations) => {
97
+ return editorExperiment('platform_editor_vanilla_dom', true) ? mentionNodeView({
98
+ options,
99
+ api,
100
+ portalProviderAPI: pmPluginFactoryParams.portalProviderAPI
101
+ })(node, view, getPos, decorations, innerDecorations) : getInlineNodeViewProducer({
102
+ pmPluginFactoryParams,
103
+ Component: MentionNodeView,
104
+ extraComponentProps: {
105
+ providerFactory: pmPluginFactoryParams.providerFactory,
106
+ pluginInjectionApi: api,
107
+ options
108
+ }
109
+ })(node, view, getPos, decorations);
110
+ }
103
111
  }
104
112
  },
105
113
  view(editorView) {
@@ -158,7 +166,7 @@ export function createMentionPlugin({
158
166
  },
159
167
  update(view, prevState) {
160
168
  const newState = view.state;
161
- if (options !== null && options !== void 0 && options.handleMentionsChanged && fg('confluence_updated_mentions_livepages')) {
169
+ if (options !== null && options !== void 0 && options.handleMentionsChanged) {
162
170
  const mentionSchema = newState.schema.nodes.mention;
163
171
  const mentionNodesBefore = findChildrenByType(prevState.doc, mentionSchema);
164
172
  const mentionLocalIdsAfter = new Set(findChildrenByType(newState.doc, mentionSchema).map(({
@@ -0,0 +1,2 @@
1
+
2
+ ._2rkoglpi{border-radius:var(--ds-border-radius,4px)}._16qs1cd0{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #091e4226,0 0 1px #091e424f)}
@@ -0,0 +1,143 @@
1
+ /* ProfileCardComponent.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./ProfileCardComponent.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { useEffect, useState, useMemo, Suspense } from 'react';
6
+ import { bind } from 'bind-event-listener';
7
+ import { Popup } from '@atlaskit/editor-common/ui';
8
+ import Portal from '@atlaskit/portal';
9
+ import { ProfileCardLazy } from '@atlaskit/profilecard/user';
10
+ const styles = {
11
+ loadingStyles: "_2rkoglpi _16qs1cd0"
12
+ };
13
+ const LoadingWrapper = ({
14
+ children,
15
+ isLoading
16
+ }) => isLoading ? /*#__PURE__*/React.createElement("div", {
17
+ className: ax([styles.loadingStyles])
18
+ }, children) : children;
19
+ export const useProfileCardState = ({
20
+ id,
21
+ provider
22
+ }) => {
23
+ const [data, setData] = useState();
24
+ const [reportingLinesData, setReportingLinesData] = useState(undefined);
25
+ const [shouldShowGiveKudos, setShouldShowGiveKudos] = useState(false);
26
+ const [teamCentralBaseUrl, setTeamCentralBaseUrl] = useState(undefined);
27
+ const [isLoading, setIsLoading] = useState(false);
28
+ const [hasError, setHasError] = useState(false);
29
+
30
+ // From: packages/people-and-teams/profilecard/src/components/User/ProfileCardTrigger.tsx
31
+ useEffect(() => {
32
+ const fetchData = async () => {
33
+ if (!id || !provider) {
34
+ return;
35
+ }
36
+ setIsLoading(true);
37
+ try {
38
+ const [data, reportingLines, shouldGiveKudos, teamCentralBaseUrl] = await Promise.all([provider === null || provider === void 0 ? void 0 : provider.resourceClient.getProfile((provider === null || provider === void 0 ? void 0 : provider.cloudId) || '', id, () => {}), provider === null || provider === void 0 ? void 0 : provider.resourceClient.getReportingLines(id), provider === null || provider === void 0 ? void 0 : provider.resourceClient.shouldShowGiveKudos(), provider === null || provider === void 0 ? void 0 : provider.resourceClient.getTeamCentralBaseUrl({
39
+ withOrgContext: true,
40
+ withSiteContext: true
41
+ })]);
42
+ setData(data);
43
+ setReportingLinesData(reportingLines);
44
+ setShouldShowGiveKudos(shouldGiveKudos !== null && shouldGiveKudos !== void 0 ? shouldGiveKudos : false);
45
+ setTeamCentralBaseUrl(teamCentralBaseUrl);
46
+ setHasError(false);
47
+ } catch (e) {
48
+ setHasError(true);
49
+ } finally {
50
+ setIsLoading(false);
51
+ }
52
+ };
53
+ fetchData();
54
+ }, [id, provider]);
55
+ return {
56
+ data,
57
+ reportingLinesData,
58
+ shouldShowGiveKudos,
59
+ teamCentralBaseUrl,
60
+ isLoading,
61
+ hasError
62
+ };
63
+ };
64
+ export function ProfileCardComponent({
65
+ profilecardProvider,
66
+ activeMention,
67
+ dom,
68
+ closeComponent
69
+ }) {
70
+ var _ref;
71
+ const [provider, setProvider] = useState(undefined);
72
+ useEffect(() => {
73
+ profilecardProvider === null || profilecardProvider === void 0 ? void 0 : profilecardProvider.then(p => {
74
+ setProvider(p);
75
+ });
76
+ }, [profilecardProvider]);
77
+ const {
78
+ id,
79
+ text,
80
+ accessLevel
81
+ } = (_ref = activeMention.attrs) !== null && _ref !== void 0 ? _ref : {};
82
+ const actions = useMemo(() => provider === null || provider === void 0 ? void 0 : provider.getActions(id, text !== null && text !== void 0 ? text : '', accessLevel), [accessLevel, id, provider, text]);
83
+ const {
84
+ data,
85
+ reportingLinesData,
86
+ shouldShowGiveKudos,
87
+ teamCentralBaseUrl,
88
+ isLoading,
89
+ hasError
90
+ } = useProfileCardState({
91
+ id,
92
+ provider
93
+ });
94
+ useEffect(() => {
95
+ return bind(window, {
96
+ type: 'keydown',
97
+ listener: e => {
98
+ if (e.key === 'Escape') {
99
+ closeComponent();
100
+ }
101
+ }
102
+ });
103
+ });
104
+ if (!provider || !activeMention) {
105
+ return null;
106
+ }
107
+ const {
108
+ cloudId
109
+ } = provider;
110
+ return /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement(Popup, {
111
+ target: dom,
112
+ absoluteOffset: {
113
+ top: 8
114
+ },
115
+ stick: true
116
+ }, /*#__PURE__*/React.createElement(Suspense, {
117
+ fallback: null
118
+ }, /*#__PURE__*/React.createElement(LoadingWrapper, {
119
+ isLoading: isLoading
120
+ }, /*#__PURE__*/React.createElement(ProfileCardLazy, {
121
+ avatarUrl: data === null || data === void 0 ? void 0 : data.avatarUrl,
122
+ accountType: data === null || data === void 0 ? void 0 : data.accountType,
123
+ status: data === null || data === void 0 ? void 0 : data.status,
124
+ statusModifiedDate: data === null || data === void 0 ? void 0 : data.statusModifiedDate,
125
+ timestring: data === null || data === void 0 ? void 0 : data.timestring,
126
+ isCurrentUser: data === null || data === void 0 ? void 0 : data.isCurrentUser,
127
+ isBot: data === null || data === void 0 ? void 0 : data.isBot,
128
+ fullName: data === null || data === void 0 ? void 0 : data.fullName,
129
+ userId: id,
130
+ cloudId: cloudId,
131
+ actions: actions,
132
+ isLoading: isLoading,
133
+ location: data === null || data === void 0 ? void 0 : data.location,
134
+ companyName: data === null || data === void 0 ? void 0 : data.companyName,
135
+ customLozenges: data === null || data === void 0 ? void 0 : data.customLozenges,
136
+ nickname: data === null || data === void 0 ? void 0 : data.nickname,
137
+ email: data === null || data === void 0 ? void 0 : data.email,
138
+ hasError: hasError,
139
+ reportingLines: reportingLinesData,
140
+ isKudosEnabled: shouldShowGiveKudos,
141
+ teamCentralBaseUrl: teamCentralBaseUrl
142
+ })))));
143
+ }
@@ -0,0 +1,191 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
5
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
6
+ import { browser } from '@atlaskit/editor-common/browser';
7
+ import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
8
+ import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
9
+ import { isResolvingMentionProvider, MentionNameStatus } from '@atlaskit/mention/resource';
10
+ import { isRestricted } from '@atlaskit/mention/types';
11
+ import { profileCardRenderer } from './profileCardRenderer';
12
+ var primitiveClassName = 'editor-mention-primitive';
13
+ var toDOM = function toDOM(node) {
14
+ // packages/elements/mention/src/components/Mention/index.tsx
15
+ var mentionAttrs = {
16
+ contenteditable: 'false',
17
+ 'data-access-level': node.attrs.accessLevel,
18
+ 'data-mention-id': node.attrs.id,
19
+ 'data-prosemirror-content-type': 'node',
20
+ 'data-prosemirror-node-inline': 'true',
21
+ 'data-prosemirror-node-name': 'mention',
22
+ 'data-prosemirror-node-view-type': 'vanilla',
23
+ class: 'mentionView-content-wrap inlineNodeView'
24
+ };
25
+ return ['span', mentionAttrs, ['span', {
26
+ class: 'zeroWidthSpaceContainer'
27
+ }, ['span', {
28
+ class: 'inlineNodeViewAddZeroWidthSpace'
29
+ }, ZERO_WIDTH_SPACE]], ['span', {
30
+ spellcheck: 'false',
31
+ class: primitiveClassName
32
+ }, node.attrs.text || '@…'], browser.android ? ['span', {
33
+ class: 'zeroWidthSpaceContainer',
34
+ contenteditable: 'false'
35
+ }, ['span', {
36
+ class: 'inlineNodeViewAddZeroWidthSpace'
37
+ }, ZERO_WIDTH_SPACE]] : ['span', {
38
+ class: 'inlineNodeViewAddZeroWidthSpace'
39
+ }, ZERO_WIDTH_SPACE]];
40
+ };
41
+ var processName = function processName(name) {
42
+ return name.status === MentionNameStatus.OK ? "@".concat(name.name || '') : "@_|unknown|_";
43
+ };
44
+ var handleProviderName = /*#__PURE__*/function () {
45
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(mentionProvider, node) {
46
+ var nameDetail, resolvedNameDetail;
47
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
48
+ while (1) switch (_context.prev = _context.next) {
49
+ case 0:
50
+ if (!(isResolvingMentionProvider(mentionProvider) && node.attrs.id && !node.attrs.text)) {
51
+ _context.next = 6;
52
+ break;
53
+ }
54
+ nameDetail = mentionProvider === null || mentionProvider === void 0 ? void 0 : mentionProvider.resolveMentionName(node.attrs.id);
55
+ _context.next = 4;
56
+ return nameDetail;
57
+ case 4:
58
+ resolvedNameDetail = _context.sent;
59
+ return _context.abrupt("return", processName(resolvedNameDetail));
60
+ case 6:
61
+ case "end":
62
+ return _context.stop();
63
+ }
64
+ }, _callee);
65
+ }));
66
+ return function handleProviderName(_x, _x2) {
67
+ return _ref.apply(this, arguments);
68
+ };
69
+ }();
70
+ var getNewState = function getNewState(isHighlighted, isRestricted) {
71
+ if (isHighlighted) {
72
+ return 'self';
73
+ }
74
+ if (isRestricted) {
75
+ return 'restricted';
76
+ }
77
+ return 'default';
78
+ };
79
+ var MentionNodeView = /*#__PURE__*/function () {
80
+ function MentionNodeView(node, config) {
81
+ var _api$mention$sharedSt,
82
+ _this = this;
83
+ _classCallCheck(this, MentionNodeView);
84
+ _defineProperty(this, "state", 'default');
85
+ var options = config.options,
86
+ api = config.api,
87
+ portalProviderAPI = config.portalProviderAPI;
88
+ var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM(node)),
89
+ dom = _DOMSerializer$render.dom,
90
+ contentDOM = _DOMSerializer$render.contentDOM;
91
+ this.dom = dom;
92
+ this.contentDOM = contentDOM;
93
+ this.config = config;
94
+ this.node = node;
95
+ var _ref2 = (_api$mention$sharedSt = api === null || api === void 0 ? void 0 : api.mention.sharedState.currentState()) !== null && _api$mention$sharedSt !== void 0 ? _api$mention$sharedSt : {},
96
+ mentionProvider = _ref2.mentionProvider;
97
+ this.updateState(mentionProvider);
98
+ this.cleanup = api === null || api === void 0 ? void 0 : api.mention.sharedState.onChange(function (_ref3) {
99
+ var nextSharedState = _ref3.nextSharedState;
100
+ _this.updateState(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.mentionProvider);
101
+ });
102
+ var _profileCardRenderer = profileCardRenderer({
103
+ dom: dom,
104
+ options: options,
105
+ portalProviderAPI: portalProviderAPI,
106
+ node: node,
107
+ api: api
108
+ }),
109
+ destroyProfileCard = _profileCardRenderer.destroyProfileCard,
110
+ removeProfileCard = _profileCardRenderer.removeProfileCard;
111
+ this.destroyProfileCard = destroyProfileCard;
112
+ this.removeProfileCard = removeProfileCard;
113
+ }
114
+ return _createClass(MentionNodeView, [{
115
+ key: "setClassList",
116
+ value: function setClassList(state) {
117
+ var mentionElement = this.getMentionPrimitive();
118
+ mentionElement === null || mentionElement === void 0 || mentionElement.classList.toggle('mention-self', state === 'self');
119
+ mentionElement === null || mentionElement === void 0 || mentionElement.classList.toggle('mention-restricted', state === 'restricted');
120
+ }
121
+ }, {
122
+ key: "getMentionPrimitive",
123
+ value: function getMentionPrimitive() {
124
+ var _this$dom$querySelect;
125
+ return this.dom instanceof HTMLElement ? (_this$dom$querySelect = this.dom.querySelector(".".concat(primitiveClassName))) !== null && _this$dom$querySelect !== void 0 ? _this$dom$querySelect : undefined : undefined;
126
+ }
127
+ }, {
128
+ key: "setTextContent",
129
+ value: function setTextContent(name) {
130
+ var _this$config$options;
131
+ if (!(this.dom instanceof HTMLElement)) {
132
+ return;
133
+ }
134
+ var mentionPrimitive = this.getMentionPrimitive();
135
+ if (mentionPrimitive && name && !this.node.attrs.text && (_this$config$options = this.config.options) !== null && _this$config$options !== void 0 && _this$config$options.sanitizePrivateContent) {
136
+ mentionPrimitive.textContent = name;
137
+ }
138
+ }
139
+ }, {
140
+ key: "updateState",
141
+ value: function () {
142
+ var _updateState = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(mentionProvider) {
143
+ var _mentionProvider$shou;
144
+ var isHighlighted, newState, name;
145
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
146
+ while (1) switch (_context2.prev = _context2.next) {
147
+ case 0:
148
+ isHighlighted = (_mentionProvider$shou = mentionProvider === null || mentionProvider === void 0 ? void 0 : mentionProvider.shouldHighlightMention({
149
+ id: this.node.attrs.id
150
+ })) !== null && _mentionProvider$shou !== void 0 ? _mentionProvider$shou : false;
151
+ newState = getNewState(isHighlighted, isRestricted(this.node.attrs.accessLevel));
152
+ if (newState !== this.state) {
153
+ this.setClassList(newState);
154
+ this.state = newState;
155
+ }
156
+ _context2.next = 5;
157
+ return handleProviderName(mentionProvider, this.node);
158
+ case 5:
159
+ name = _context2.sent;
160
+ this.setTextContent(name);
161
+ case 7:
162
+ case "end":
163
+ return _context2.stop();
164
+ }
165
+ }, _callee2, this);
166
+ }));
167
+ function updateState(_x3) {
168
+ return _updateState.apply(this, arguments);
169
+ }
170
+ return updateState;
171
+ }()
172
+ }, {
173
+ key: "destroy",
174
+ value: function destroy() {
175
+ var _this$cleanup, _this$destroyProfileC;
176
+ (_this$cleanup = this.cleanup) === null || _this$cleanup === void 0 || _this$cleanup.call(this);
177
+ (_this$destroyProfileC = this.destroyProfileCard) === null || _this$destroyProfileC === void 0 || _this$destroyProfileC.call(this);
178
+ }
179
+ }, {
180
+ key: "deselectNode",
181
+ value: function deselectNode() {
182
+ var _this$removeProfileCa;
183
+ (_this$removeProfileCa = this.removeProfileCard) === null || _this$removeProfileCa === void 0 || _this$removeProfileCa.call(this);
184
+ }
185
+ }]);
186
+ }();
187
+ export var mentionNodeView = function mentionNodeView(config) {
188
+ return function (node) {
189
+ return new MentionNodeView(node, config);
190
+ };
191
+ };
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { bind } from 'bind-event-listener';
3
+ import uuid from 'uuid/v4';
4
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
+ import { ProfileCardComponent } from '../ui/ProfileCardComponent';
6
+ export var profileCardRenderer = function profileCardRenderer(_ref) {
7
+ var dom = _ref.dom,
8
+ options = _ref.options,
9
+ portalProviderAPI = _ref.portalProviderAPI,
10
+ node = _ref.node,
11
+ api = _ref.api;
12
+ var renderingProfileCard = false;
13
+ var key = uuid();
14
+ var cleanupSelection;
15
+ var removeProfileCard = function removeProfileCard() {
16
+ var _cleanupSelection;
17
+ portalProviderAPI.remove(key);
18
+ renderingProfileCard = false;
19
+ (_cleanupSelection = cleanupSelection) === null || _cleanupSelection === void 0 || _cleanupSelection();
20
+ };
21
+ var listenerCleanup = bind(dom, {
22
+ type: 'click',
23
+ listener: function listener() {
24
+ if (dom instanceof HTMLElement && options !== null && options !== void 0 && options.profilecardProvider && !renderingProfileCard) {
25
+ var _api$selection;
26
+ renderingProfileCard = true;
27
+ portalProviderAPI.render(function () {
28
+ return /*#__PURE__*/React.createElement(ProfileCardComponent, {
29
+ activeMention: node,
30
+ profilecardProvider: options === null || options === void 0 ? void 0 : options.profilecardProvider,
31
+ dom: dom,
32
+ closeComponent: removeProfileCard
33
+ });
34
+ }, dom, key);
35
+ // If we change the selection we should also remove the profile card. The "deselectNode"
36
+ // should usually catch this, but it's possible (ie. on triple click) for this not to be called
37
+ // which means the profile card gets stuck open until you click + change selection
38
+ cleanupSelection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.sharedState.onChange(function (_ref2) {
39
+ var nextSharedState = _ref2.nextSharedState;
40
+ var selection = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.selection;
41
+ if (selection instanceof NodeSelection ? selection.node === node : false) {
42
+ return;
43
+ }
44
+ removeProfileCard === null || removeProfileCard === void 0 || removeProfileCard();
45
+ });
46
+ }
47
+ }
48
+ });
49
+ return {
50
+ destroyProfileCard: function destroyProfileCard() {
51
+ listenerCleanup();
52
+ removeProfileCard === null || removeProfileCard === void 0 || removeProfileCard();
53
+ },
54
+ removeProfileCard: removeProfileCard
55
+ };
56
+ };