@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.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/nodeviews/mentionNodeView.js +198 -0
- package/dist/cjs/nodeviews/profileCardRenderer.js +63 -0
- package/dist/cjs/pm-plugins/main.js +19 -11
- package/dist/cjs/ui/ProfileCardComponent.compiled.css +2 -0
- package/dist/cjs/ui/ProfileCardComponent.js +205 -0
- package/dist/es2019/nodeviews/mentionNodeView.js +139 -0
- package/dist/es2019/nodeviews/profileCardRenderer.js +56 -0
- package/dist/es2019/pm-plugins/main.js +19 -11
- package/dist/es2019/ui/ProfileCardComponent.compiled.css +2 -0
- package/dist/es2019/ui/ProfileCardComponent.js +143 -0
- package/dist/esm/nodeviews/mentionNodeView.js +191 -0
- package/dist/esm/nodeviews/profileCardRenderer.js +56 -0
- package/dist/esm/pm-plugins/main.js +19 -11
- package/dist/esm/ui/ProfileCardComponent.compiled.css +2 -0
- package/dist/esm/ui/ProfileCardComponent.js +194 -0
- package/dist/types/mentionsPluginType.d.ts +3 -1
- package/dist/types/nodeviews/mentionNodeView.d.ts +12 -0
- package/dist/types/nodeviews/profileCardRenderer.d.ts +15 -0
- package/dist/types/ui/ProfileCardComponent.d.ts +23 -0
- package/dist/types-ts4.5/mentionsPluginType.d.ts +3 -1
- package/dist/types-ts4.5/nodeviews/mentionNodeView.d.ts +12 -0
- package/dist/types-ts4.5/nodeviews/profileCardRenderer.d.ts +15 -0
- package/dist/types-ts4.5/ui/ProfileCardComponent.d.ts +23 -0
- package/package.json +10 -9
|
@@ -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.
|
|
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:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
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,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
|
+
};
|