@atlaskit/editor-plugin-mentions 4.3.2 → 4.4.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 CHANGED
@@ -1,5 +1,27 @@
1
1
  # @atlaskit/editor-plugin-mentions
2
2
 
3
+ ## 4.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#139139](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/139139)
8
+ [`7f6b665d778dd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7f6b665d778dd) -
9
+ [https://product-fabric.atlassian.net/browse/ED-27499](ED-27499) - the new
10
+ `@atlassian/confluence-presets` package with Confluence `full-page` preset is created
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+
16
+ ## 4.3.3
17
+
18
+ ### Patch Changes
19
+
20
+ - [#138789](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/138789)
21
+ [`eeb167efe5e64`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/eeb167efe5e64) -
22
+ Setup focus trap for profile card provider in vanilla mention version
23
+ - Updated dependencies
24
+
3
25
  ## 4.3.2
4
26
 
5
27
  ### Patch Changes
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.mentionNodeView = void 0;
7
+ exports.MentionNodeView = void 0;
8
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
9
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
10
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
@@ -16,7 +16,12 @@ var _model = require("@atlaskit/editor-prosemirror/model");
16
16
  var _resource = require("@atlaskit/mention/resource");
17
17
  var _types = require("@atlaskit/mention/types");
18
18
  var _profileCardRenderer2 = require("./profileCardRenderer");
19
+ 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; }
20
+ 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) { (0, _defineProperty2.default)(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; }
19
21
  var primitiveClassName = 'editor-mention-primitive';
22
+ var getAccessibilityLabelFromName = function getAccessibilityLabelFromName(name) {
23
+ return name.replace(/^@/, '');
24
+ };
20
25
  var toDOM = function toDOM(node) {
21
26
  // packages/elements/mention/src/components/Mention/index.tsx
22
27
  var mentionAttrs = {
@@ -83,9 +88,10 @@ var getNewState = function getNewState(isHighlighted, isRestricted) {
83
88
  }
84
89
  return 'default';
85
90
  };
86
- var MentionNodeView = /*#__PURE__*/function () {
91
+ var MentionNodeView = exports.MentionNodeView = /*#__PURE__*/function () {
87
92
  function MentionNodeView(node, config) {
88
- var _api$mention$sharedSt,
93
+ var _this$domElement$quer,
94
+ _api$mention$sharedSt,
89
95
  _this = this;
90
96
  (0, _classCallCheck2.default)(this, MentionNodeView);
91
97
  (0, _defineProperty2.default)(this, "state", 'default');
@@ -99,6 +105,8 @@ var MentionNodeView = /*#__PURE__*/function () {
99
105
  this.contentDOM = contentDOM;
100
106
  this.config = config;
101
107
  this.node = node;
108
+ this.domElement = dom instanceof HTMLElement ? dom : undefined;
109
+ this.mentionPrimitiveElement = this.domElement ? (_this$domElement$quer = this.domElement.querySelector(".".concat(primitiveClassName))) !== null && _this$domElement$quer !== void 0 ? _this$domElement$quer : undefined : undefined;
102
110
  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 : {},
103
111
  mentionProvider = _ref2.mentionProvider;
104
112
  this.updateState(mentionProvider);
@@ -115,39 +123,38 @@ var MentionNodeView = /*#__PURE__*/function () {
115
123
  }),
116
124
  destroyProfileCard = _profileCardRenderer.destroyProfileCard,
117
125
  removeProfileCard = _profileCardRenderer.removeProfileCard;
126
+ // Accessibility attributes - based on `packages/people-and-teams/profilecard/src/components/User/ProfileCardTrigger.tsx`
127
+ if (this.domElement && options !== null && options !== void 0 && options.profilecardProvider) {
128
+ if (node.attrs.text) {
129
+ this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(node.attrs.text));
130
+ }
131
+ this.domElement.setAttribute('aria-expanded', 'false');
132
+ this.domElement.setAttribute('role', 'button');
133
+ this.domElement.setAttribute('tabindex', '0');
134
+ this.domElement.setAttribute('aria-haspopup', 'dialog');
135
+ }
118
136
  this.destroyProfileCard = destroyProfileCard;
119
137
  this.removeProfileCard = removeProfileCard;
120
138
  }
121
139
  return (0, _createClass2.default)(MentionNodeView, [{
122
140
  key: "setClassList",
123
141
  value: function setClassList(state) {
124
- var mentionElement = this.getMentionPrimitive();
125
- mentionElement === null || mentionElement === void 0 || mentionElement.classList.toggle('mention-self', state === 'self');
126
- mentionElement === null || mentionElement === void 0 || mentionElement.classList.toggle('mention-restricted', state === 'restricted');
127
- }
128
- }, {
129
- key: "getMentionPrimitive",
130
- value: function getMentionPrimitive() {
131
- var _this$dom$querySelect;
132
- return this.dom instanceof HTMLElement ? (_this$dom$querySelect = this.dom.querySelector(".".concat(primitiveClassName))) !== null && _this$dom$querySelect !== void 0 ? _this$dom$querySelect : undefined : undefined;
142
+ var _this$mentionPrimitiv, _this$mentionPrimitiv2;
143
+ (_this$mentionPrimitiv = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv === void 0 || _this$mentionPrimitiv.classList.toggle('mention-self', state === 'self');
144
+ (_this$mentionPrimitiv2 = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv2 === void 0 || _this$mentionPrimitiv2.classList.toggle('mention-restricted', state === 'restricted');
133
145
  }
134
146
  }, {
135
147
  key: "setTextContent",
136
148
  value: function setTextContent(name) {
137
- var _this$config$options;
138
- if (!(this.dom instanceof HTMLElement)) {
139
- return;
140
- }
141
- var mentionPrimitive = this.getMentionPrimitive();
142
- if (mentionPrimitive && name && !this.node.attrs.text && (_this$config$options = this.config.options) !== null && _this$config$options !== void 0 && _this$config$options.sanitizePrivateContent) {
143
- mentionPrimitive.textContent = name;
149
+ if (name && !this.node.attrs.text && this.mentionPrimitiveElement) {
150
+ this.mentionPrimitiveElement.textContent = name;
144
151
  }
145
152
  }
146
153
  }, {
147
154
  key: "updateState",
148
155
  value: function () {
149
156
  var _updateState = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(mentionProvider) {
150
- var _mentionProvider$shou;
157
+ var _mentionProvider$shou, _this$config$options;
151
158
  var isHighlighted, newState, name;
152
159
  return _regenerator.default.wrap(function _callee2$(_context2) {
153
160
  while (1) switch (_context2.prev = _context2.next) {
@@ -165,7 +172,10 @@ var MentionNodeView = /*#__PURE__*/function () {
165
172
  case 5:
166
173
  name = _context2.sent;
167
174
  this.setTextContent(name);
168
- case 7:
175
+ if (name && this.domElement && (_this$config$options = this.config.options) !== null && _this$config$options !== void 0 && _this$config$options.profilecardProvider) {
176
+ this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(name));
177
+ }
178
+ case 8:
169
179
  case "end":
170
180
  return _context2.stop();
171
181
  }
@@ -176,6 +186,28 @@ var MentionNodeView = /*#__PURE__*/function () {
176
186
  }
177
187
  return updateState;
178
188
  }()
189
+ }, {
190
+ key: "nodeIsEqual",
191
+ value: function nodeIsEqual(nextNode) {
192
+ var _this$config$options2;
193
+ if ((_this$config$options2 = this.config.options) !== null && _this$config$options2 !== void 0 && _this$config$options2.sanitizePrivateContent) {
194
+ // Compare nodes but ignore the text parameter as it may be sanitized
195
+ var nextNodeAttrs = _objectSpread(_objectSpread({}, nextNode.attrs), {}, {
196
+ text: this.node.attrs.text
197
+ });
198
+ return this.node.hasMarkup(nextNode.type, nextNodeAttrs, nextNode.marks);
199
+ }
200
+ return this.node.sameMarkup(nextNode);
201
+ }
202
+ }, {
203
+ key: "update",
204
+ value: function update(node) {
205
+ if (!this.nodeIsEqual(node)) {
206
+ return false;
207
+ }
208
+ this.node = node;
209
+ return true;
210
+ }
179
211
  }, {
180
212
  key: "destroy",
181
213
  value: function destroy() {
@@ -190,9 +222,4 @@ var MentionNodeView = /*#__PURE__*/function () {
190
222
  (_this$removeProfileCa = this.removeProfileCard) === null || _this$removeProfileCa === void 0 || _this$removeProfileCa.call(this);
191
223
  }
192
224
  }]);
193
- }();
194
- var mentionNodeView = exports.mentionNodeView = function mentionNodeView(config) {
195
- return function (node) {
196
- return new MentionNodeView(node, config);
197
- };
198
- };
225
+ }();
@@ -21,6 +21,9 @@ var profileCardRenderer = exports.profileCardRenderer = function profileCardRend
21
21
  var cleanupSelection;
22
22
  var removeProfileCard = function removeProfileCard() {
23
23
  var _cleanupSelection;
24
+ if (dom instanceof HTMLElement) {
25
+ dom.setAttribute('aria-expanded', 'false');
26
+ }
24
27
  portalProviderAPI.remove(key);
25
28
  renderingProfileCard = false;
26
29
  (_cleanupSelection = cleanupSelection) === null || _cleanupSelection === void 0 || _cleanupSelection();
@@ -30,6 +33,7 @@ var profileCardRenderer = exports.profileCardRenderer = function profileCardRend
30
33
  listener: function listener() {
31
34
  if (dom instanceof HTMLElement && options !== null && options !== void 0 && options.profilecardProvider && !renderingProfileCard) {
32
35
  var _api$selection;
36
+ dom.setAttribute('aria-expanded', 'true');
33
37
  renderingProfileCard = true;
34
38
  portalProviderAPI.render(function () {
35
39
  return /*#__PURE__*/_react.default.createElement(_ProfileCardComponent.ProfileCardComponent, {
@@ -26,7 +26,7 @@ var ACTIONS = exports.ACTIONS = {
26
26
  SET_PROVIDER: 'SET_PROVIDER'
27
27
  };
28
28
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
29
- var PACKAGE_VERSION = "4.3.2";
29
+ var PACKAGE_VERSION = "4.4.0";
30
30
  var setProvider = function setProvider(provider) {
31
31
  return function (state, dispatch) {
32
32
  if (dispatch) {
@@ -102,11 +102,13 @@ function createMentionPlugin(_ref) {
102
102
  props: {
103
103
  nodeViews: {
104
104
  mention: function mention(node, view, getPos, decorations, innerDecorations) {
105
- return (0, _experiments.editorExperiment)('platform_editor_vanilla_dom', true) ? (0, _mentionNodeView.mentionNodeView)({
105
+ return (0, _experiments.editorExperiment)('platform_editor_vanilla_dom', true, {
106
+ exposure: true
107
+ }) ? new _mentionNodeView.MentionNodeView(node, {
106
108
  options: options,
107
109
  api: api,
108
110
  portalProviderAPI: pmPluginFactoryParams.portalProviderAPI
109
- })(node, view, getPos, decorations, innerDecorations) : (0, _reactNodeView.getInlineNodeViewProducer)({
111
+ }) : (0, _reactNodeView.getInlineNodeViewProducer)({
110
112
  pmPluginFactoryParams: pmPluginFactoryParams,
111
113
  Component: _mention.MentionNodeView,
112
114
  extraComponentProps: {
@@ -5,4 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.MENTION_PROVIDER_UNDEFINED = exports.MENTION_PROVIDER_REJECTED = void 0;
7
7
  var MENTION_PROVIDER_REJECTED = exports.MENTION_PROVIDER_REJECTED = 'REJECTED';
8
- var MENTION_PROVIDER_UNDEFINED = exports.MENTION_PROVIDER_UNDEFINED = 'UNDEFINED';
8
+ var MENTION_PROVIDER_UNDEFINED = exports.MENTION_PROVIDER_UNDEFINED = 'UNDEFINED';
9
+
10
+ /**
11
+ * @private
12
+ * @deprecated Use {@link MentionsPluginOptions} instead.
13
+ * @see https://product-fabric.atlassian.net/browse/ED-27496
14
+ */
@@ -5,9 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.Popup = Popup;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
8
9
  var _react = _interopRequireDefault(require("react"));
9
10
  var _popper = require("@atlaskit/popper");
10
11
  var _portal = _interopRequireDefault(require("@atlaskit/portal"));
12
+ var _useFocusTrap = require("./useFocusTrap");
11
13
  /**
12
14
  * A popup wrapper to match the behaviour of `@atlaskit/popup`
13
15
  *
@@ -22,21 +24,35 @@ var _portal = _interopRequireDefault(require("@atlaskit/portal"));
22
24
  function Popup(_ref) {
23
25
  var referenceElement = _ref.referenceElement,
24
26
  children = _ref.children;
27
+ var _React$useState = _react.default.useState(null),
28
+ _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
29
+ targetRef = _React$useState2[0],
30
+ setPopupRef = _React$useState2[1];
31
+ (0, _useFocusTrap.useFocusTrap)({
32
+ targetRef: targetRef
33
+ });
25
34
  return /*#__PURE__*/_react.default.createElement(_portal.default, null, /*#__PURE__*/_react.default.createElement(_popper.Popper, {
26
35
  referenceElement: referenceElement,
27
36
  offset: [0, 8],
28
37
  placement: "bottom-end",
29
38
  strategy: "fixed"
30
39
  }, function (_ref2) {
31
- var ref = _ref2.ref,
40
+ var _ref3 = _ref2.ref,
32
41
  style = _ref2.style;
33
- return (
34
- /*#__PURE__*/
42
+ return /*#__PURE__*/_react.default.createElement("div", {
43
+ ref: function ref(node) {
44
+ if (node) {
45
+ if (typeof _ref3 === 'function') {
46
+ _ref3(node);
47
+ } else {
48
+ _ref3.current = node;
49
+ }
50
+ setPopupRef(node);
51
+ }
52
+ }
35
53
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
36
- _react.default.createElement("div", {
37
- ref: ref,
38
- style: style
39
- }, children)
40
- );
54
+ ,
55
+ style: style
56
+ }, children);
41
57
  }));
42
58
  }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useFocusTrap = void 0;
8
+ var _react = require("react");
9
+ var _focusTrap = _interopRequireDefault(require("focus-trap"));
10
+ /**
11
+ * Custom hook to add focus trap
12
+ * used for focus trap in ReactionPicker
13
+ * copied from useFocusManager in @atlaskit/popup
14
+ */
15
+
16
+ var useFocusTrap = exports.useFocusTrap = function useFocusTrap(_ref) {
17
+ var targetRef = _ref.targetRef;
18
+ (0, _react.useEffect)(function () {
19
+ if (!targetRef) {
20
+ return;
21
+ }
22
+ var trapConfig = {
23
+ clickOutsideDeactivates: true,
24
+ escapeDeactivates: true,
25
+ initialFocus: targetRef,
26
+ fallbackFocus: targetRef,
27
+ returnFocusOnDeactivate: true
28
+ };
29
+ var focusTrap = (0, _focusTrap.default)(targetRef, trapConfig);
30
+
31
+ // wait for the popup to reposition itself before we focus
32
+ var frameId = requestAnimationFrame(function () {
33
+ frameId = null;
34
+ focusTrap.activate();
35
+ });
36
+ return function () {
37
+ if (frameId !== null) {
38
+ cancelAnimationFrame(frameId);
39
+ frameId = null;
40
+ }
41
+ focusTrap.deactivate();
42
+ };
43
+ }, [targetRef]);
44
+ };
@@ -6,6 +6,7 @@ import { isResolvingMentionProvider, MentionNameStatus } from '@atlaskit/mention
6
6
  import { isRestricted } from '@atlaskit/mention/types';
7
7
  import { profileCardRenderer } from './profileCardRenderer';
8
8
  const primitiveClassName = 'editor-mention-primitive';
9
+ const getAccessibilityLabelFromName = name => name.replace(/^@/u, '');
9
10
  const toDOM = node => {
10
11
  // packages/elements/mention/src/components/Mention/index.tsx
11
12
  const mentionAttrs = {
@@ -53,9 +54,9 @@ const getNewState = (isHighlighted, isRestricted) => {
53
54
  }
54
55
  return 'default';
55
56
  };
56
- class MentionNodeView {
57
+ export class MentionNodeView {
57
58
  constructor(node, config) {
58
- var _api$mention$sharedSt;
59
+ var _this$domElement$quer, _api$mention$sharedSt;
59
60
  _defineProperty(this, "state", 'default');
60
61
  const {
61
62
  options,
@@ -70,6 +71,8 @@ class MentionNodeView {
70
71
  this.contentDOM = contentDOM;
71
72
  this.config = config;
72
73
  this.node = node;
74
+ this.domElement = dom instanceof HTMLElement ? dom : undefined;
75
+ this.mentionPrimitiveElement = this.domElement ? (_this$domElement$quer = this.domElement.querySelector(`.${primitiveClassName}`)) !== null && _this$domElement$quer !== void 0 ? _this$domElement$quer : undefined : undefined;
73
76
  const {
74
77
  mentionProvider
75
78
  } = (_api$mention$sharedSt = api === null || api === void 0 ? void 0 : api.mention.sharedState.currentState()) !== null && _api$mention$sharedSt !== void 0 ? _api$mention$sharedSt : {};
@@ -89,30 +92,31 @@ class MentionNodeView {
89
92
  node,
90
93
  api
91
94
  });
95
+ // Accessibility attributes - based on `packages/people-and-teams/profilecard/src/components/User/ProfileCardTrigger.tsx`
96
+ if (this.domElement && options !== null && options !== void 0 && options.profilecardProvider) {
97
+ if (node.attrs.text) {
98
+ this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(node.attrs.text));
99
+ }
100
+ this.domElement.setAttribute('aria-expanded', 'false');
101
+ this.domElement.setAttribute('role', 'button');
102
+ this.domElement.setAttribute('tabindex', '0');
103
+ this.domElement.setAttribute('aria-haspopup', 'dialog');
104
+ }
92
105
  this.destroyProfileCard = destroyProfileCard;
93
106
  this.removeProfileCard = removeProfileCard;
94
107
  }
95
108
  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;
109
+ var _this$mentionPrimitiv, _this$mentionPrimitiv2;
110
+ (_this$mentionPrimitiv = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv === void 0 ? void 0 : _this$mentionPrimitiv.classList.toggle('mention-self', state === 'self');
111
+ (_this$mentionPrimitiv2 = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv2 === void 0 ? void 0 : _this$mentionPrimitiv2.classList.toggle('mention-restricted', state === 'restricted');
103
112
  }
104
113
  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;
114
+ if (name && !this.node.attrs.text && this.mentionPrimitiveElement) {
115
+ this.mentionPrimitiveElement.textContent = name;
112
116
  }
113
117
  }
114
118
  async updateState(mentionProvider) {
115
- var _mentionProvider$shou;
119
+ var _mentionProvider$shou, _this$config$options;
116
120
  const isHighlighted = (_mentionProvider$shou = mentionProvider === null || mentionProvider === void 0 ? void 0 : mentionProvider.shouldHighlightMention({
117
121
  id: this.node.attrs.id
118
122
  })) !== null && _mentionProvider$shou !== void 0 ? _mentionProvider$shou : false;
@@ -123,6 +127,28 @@ class MentionNodeView {
123
127
  }
124
128
  const name = await handleProviderName(mentionProvider, this.node);
125
129
  this.setTextContent(name);
130
+ if (name && this.domElement && (_this$config$options = this.config.options) !== null && _this$config$options !== void 0 && _this$config$options.profilecardProvider) {
131
+ this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(name));
132
+ }
133
+ }
134
+ nodeIsEqual(nextNode) {
135
+ var _this$config$options2;
136
+ if ((_this$config$options2 = this.config.options) !== null && _this$config$options2 !== void 0 && _this$config$options2.sanitizePrivateContent) {
137
+ // Compare nodes but ignore the text parameter as it may be sanitized
138
+ const nextNodeAttrs = {
139
+ ...nextNode.attrs,
140
+ text: this.node.attrs.text
141
+ };
142
+ return this.node.hasMarkup(nextNode.type, nextNodeAttrs, nextNode.marks);
143
+ }
144
+ return this.node.sameMarkup(nextNode);
145
+ }
146
+ update(node) {
147
+ if (!this.nodeIsEqual(node)) {
148
+ return false;
149
+ }
150
+ this.node = node;
151
+ return true;
126
152
  }
127
153
  destroy() {
128
154
  var _this$cleanup, _this$destroyProfileC;
@@ -133,7 +159,4 @@ class MentionNodeView {
133
159
  var _this$removeProfileCa;
134
160
  (_this$removeProfileCa = this.removeProfileCard) === null || _this$removeProfileCa === void 0 ? void 0 : _this$removeProfileCa.call(this);
135
161
  }
136
- }
137
- export const mentionNodeView = config => node => {
138
- return new MentionNodeView(node, config);
139
- };
162
+ }
@@ -15,6 +15,9 @@ export const profileCardRenderer = ({
15
15
  let cleanupSelection;
16
16
  const removeProfileCard = () => {
17
17
  var _cleanupSelection;
18
+ if (dom instanceof HTMLElement) {
19
+ dom.setAttribute('aria-expanded', 'false');
20
+ }
18
21
  portalProviderAPI.remove(key);
19
22
  renderingProfileCard = false;
20
23
  (_cleanupSelection = cleanupSelection) === null || _cleanupSelection === void 0 ? void 0 : _cleanupSelection();
@@ -24,6 +27,7 @@ export const profileCardRenderer = ({
24
27
  listener: () => {
25
28
  if (dom instanceof HTMLElement && options !== null && options !== void 0 && options.profilecardProvider && !renderingProfileCard) {
26
29
  var _api$selection;
30
+ dom.setAttribute('aria-expanded', 'true');
27
31
  renderingProfileCard = true;
28
32
  portalProviderAPI.render(() => /*#__PURE__*/React.createElement(ProfileCardComponent, {
29
33
  activeMention: node,
@@ -7,7 +7,7 @@ import { ComponentNames } from '@atlaskit/mention/types';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
8
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
9
9
  import { MentionNodeView } from '../nodeviews/mention';
10
- import { mentionNodeView } from '../nodeviews/mentionNodeView';
10
+ import { MentionNodeView as VanillaMentionNodeView } from '../nodeviews/mentionNodeView';
11
11
  import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types';
12
12
  import { mentionPluginKey } from './key';
13
13
  import { canMentionBeCreatedInRange } from './utils';
@@ -15,7 +15,7 @@ export const ACTIONS = {
15
15
  SET_PROVIDER: 'SET_PROVIDER'
16
16
  };
17
17
  const PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
18
- const PACKAGE_VERSION = "4.3.2";
18
+ const PACKAGE_VERSION = "4.4.0";
19
19
  const setProvider = provider => (state, dispatch) => {
20
20
  if (dispatch) {
21
21
  dispatch(state.tr.setMeta(mentionPluginKey, {
@@ -94,11 +94,13 @@ export function createMentionPlugin({
94
94
  props: {
95
95
  nodeViews: {
96
96
  mention: (node, view, getPos, decorations, innerDecorations) => {
97
- return editorExperiment('platform_editor_vanilla_dom', true) ? mentionNodeView({
97
+ return editorExperiment('platform_editor_vanilla_dom', true, {
98
+ exposure: true
99
+ }) ? new VanillaMentionNodeView(node, {
98
100
  options,
99
101
  api,
100
102
  portalProviderAPI: pmPluginFactoryParams.portalProviderAPI
101
- })(node, view, getPos, decorations, innerDecorations) : getInlineNodeViewProducer({
103
+ }) : getInlineNodeViewProducer({
102
104
  pmPluginFactoryParams,
103
105
  Component: MentionNodeView,
104
106
  extraComponentProps: {
@@ -1,2 +1,8 @@
1
1
  export const MENTION_PROVIDER_REJECTED = 'REJECTED';
2
- export const MENTION_PROVIDER_UNDEFINED = 'UNDEFINED';
2
+ export const MENTION_PROVIDER_UNDEFINED = 'UNDEFINED';
3
+
4
+ /**
5
+ * @private
6
+ * @deprecated Use {@link MentionsPluginOptions} instead.
7
+ * @see https://product-fabric.atlassian.net/browse/ED-27496
8
+ */
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Popper as ReactPopper } from '@atlaskit/popper';
3
3
  import Portal from '@atlaskit/portal';
4
+ import { useFocusTrap } from './useFocusTrap';
4
5
  /**
5
6
  * A popup wrapper to match the behaviour of `@atlaskit/popup`
6
7
  *
@@ -16,6 +17,10 @@ export function Popup({
16
17
  referenceElement,
17
18
  children
18
19
  }) {
20
+ const [targetRef, setPopupRef] = React.useState(null);
21
+ useFocusTrap({
22
+ targetRef: targetRef
23
+ });
19
24
  return /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement(ReactPopper, {
20
25
  referenceElement: referenceElement,
21
26
  offset: [0, 8],
@@ -24,11 +29,19 @@ export function Popup({
24
29
  }, ({
25
30
  ref,
26
31
  style
27
- }) =>
28
- /*#__PURE__*/
29
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
30
- React.createElement("div", {
31
- ref: ref,
32
+ }) => /*#__PURE__*/React.createElement("div", {
33
+ ref: node => {
34
+ if (node) {
35
+ if (typeof ref === 'function') {
36
+ ref(node);
37
+ } else {
38
+ ref.current = node;
39
+ }
40
+ setPopupRef(node);
41
+ }
42
+ }
43
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
44
+ ,
32
45
  style: style
33
46
  }, children)));
34
47
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Custom hook to add focus trap
3
+ * used for focus trap in ReactionPicker
4
+ * copied from useFocusManager in @atlaskit/popup
5
+ */
6
+ import { useEffect } from 'react';
7
+ import createFocusTrap from 'focus-trap';
8
+ export const useFocusTrap = ({
9
+ targetRef
10
+ }) => {
11
+ useEffect(() => {
12
+ if (!targetRef) {
13
+ return;
14
+ }
15
+ const trapConfig = {
16
+ clickOutsideDeactivates: true,
17
+ escapeDeactivates: true,
18
+ initialFocus: targetRef,
19
+ fallbackFocus: targetRef,
20
+ returnFocusOnDeactivate: true
21
+ };
22
+ const focusTrap = createFocusTrap(targetRef, trapConfig);
23
+
24
+ // wait for the popup to reposition itself before we focus
25
+ let frameId = requestAnimationFrame(() => {
26
+ frameId = null;
27
+ focusTrap.activate();
28
+ });
29
+ return () => {
30
+ if (frameId !== null) {
31
+ cancelAnimationFrame(frameId);
32
+ frameId = null;
33
+ }
34
+ focusTrap.deactivate();
35
+ };
36
+ }, [targetRef]);
37
+ };
@@ -2,6 +2,8 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
5
+ 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; }
6
+ 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; }
5
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
6
8
  import { browser } from '@atlaskit/editor-common/browser';
7
9
  import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
@@ -10,6 +12,9 @@ import { isResolvingMentionProvider, MentionNameStatus } from '@atlaskit/mention
10
12
  import { isRestricted } from '@atlaskit/mention/types';
11
13
  import { profileCardRenderer } from './profileCardRenderer';
12
14
  var primitiveClassName = 'editor-mention-primitive';
15
+ var getAccessibilityLabelFromName = function getAccessibilityLabelFromName(name) {
16
+ return name.replace(/^@/, '');
17
+ };
13
18
  var toDOM = function toDOM(node) {
14
19
  // packages/elements/mention/src/components/Mention/index.tsx
15
20
  var mentionAttrs = {
@@ -76,9 +81,10 @@ var getNewState = function getNewState(isHighlighted, isRestricted) {
76
81
  }
77
82
  return 'default';
78
83
  };
79
- var MentionNodeView = /*#__PURE__*/function () {
84
+ export var MentionNodeView = /*#__PURE__*/function () {
80
85
  function MentionNodeView(node, config) {
81
- var _api$mention$sharedSt,
86
+ var _this$domElement$quer,
87
+ _api$mention$sharedSt,
82
88
  _this = this;
83
89
  _classCallCheck(this, MentionNodeView);
84
90
  _defineProperty(this, "state", 'default');
@@ -92,6 +98,8 @@ var MentionNodeView = /*#__PURE__*/function () {
92
98
  this.contentDOM = contentDOM;
93
99
  this.config = config;
94
100
  this.node = node;
101
+ this.domElement = dom instanceof HTMLElement ? dom : undefined;
102
+ this.mentionPrimitiveElement = this.domElement ? (_this$domElement$quer = this.domElement.querySelector(".".concat(primitiveClassName))) !== null && _this$domElement$quer !== void 0 ? _this$domElement$quer : undefined : undefined;
95
103
  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
104
  mentionProvider = _ref2.mentionProvider;
97
105
  this.updateState(mentionProvider);
@@ -108,39 +116,38 @@ var MentionNodeView = /*#__PURE__*/function () {
108
116
  }),
109
117
  destroyProfileCard = _profileCardRenderer.destroyProfileCard,
110
118
  removeProfileCard = _profileCardRenderer.removeProfileCard;
119
+ // Accessibility attributes - based on `packages/people-and-teams/profilecard/src/components/User/ProfileCardTrigger.tsx`
120
+ if (this.domElement && options !== null && options !== void 0 && options.profilecardProvider) {
121
+ if (node.attrs.text) {
122
+ this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(node.attrs.text));
123
+ }
124
+ this.domElement.setAttribute('aria-expanded', 'false');
125
+ this.domElement.setAttribute('role', 'button');
126
+ this.domElement.setAttribute('tabindex', '0');
127
+ this.domElement.setAttribute('aria-haspopup', 'dialog');
128
+ }
111
129
  this.destroyProfileCard = destroyProfileCard;
112
130
  this.removeProfileCard = removeProfileCard;
113
131
  }
114
132
  return _createClass(MentionNodeView, [{
115
133
  key: "setClassList",
116
134
  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;
135
+ var _this$mentionPrimitiv, _this$mentionPrimitiv2;
136
+ (_this$mentionPrimitiv = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv === void 0 || _this$mentionPrimitiv.classList.toggle('mention-self', state === 'self');
137
+ (_this$mentionPrimitiv2 = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv2 === void 0 || _this$mentionPrimitiv2.classList.toggle('mention-restricted', state === 'restricted');
126
138
  }
127
139
  }, {
128
140
  key: "setTextContent",
129
141
  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;
142
+ if (name && !this.node.attrs.text && this.mentionPrimitiveElement) {
143
+ this.mentionPrimitiveElement.textContent = name;
137
144
  }
138
145
  }
139
146
  }, {
140
147
  key: "updateState",
141
148
  value: function () {
142
149
  var _updateState = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(mentionProvider) {
143
- var _mentionProvider$shou;
150
+ var _mentionProvider$shou, _this$config$options;
144
151
  var isHighlighted, newState, name;
145
152
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
146
153
  while (1) switch (_context2.prev = _context2.next) {
@@ -158,7 +165,10 @@ var MentionNodeView = /*#__PURE__*/function () {
158
165
  case 5:
159
166
  name = _context2.sent;
160
167
  this.setTextContent(name);
161
- case 7:
168
+ if (name && this.domElement && (_this$config$options = this.config.options) !== null && _this$config$options !== void 0 && _this$config$options.profilecardProvider) {
169
+ this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(name));
170
+ }
171
+ case 8:
162
172
  case "end":
163
173
  return _context2.stop();
164
174
  }
@@ -169,6 +179,28 @@ var MentionNodeView = /*#__PURE__*/function () {
169
179
  }
170
180
  return updateState;
171
181
  }()
182
+ }, {
183
+ key: "nodeIsEqual",
184
+ value: function nodeIsEqual(nextNode) {
185
+ var _this$config$options2;
186
+ if ((_this$config$options2 = this.config.options) !== null && _this$config$options2 !== void 0 && _this$config$options2.sanitizePrivateContent) {
187
+ // Compare nodes but ignore the text parameter as it may be sanitized
188
+ var nextNodeAttrs = _objectSpread(_objectSpread({}, nextNode.attrs), {}, {
189
+ text: this.node.attrs.text
190
+ });
191
+ return this.node.hasMarkup(nextNode.type, nextNodeAttrs, nextNode.marks);
192
+ }
193
+ return this.node.sameMarkup(nextNode);
194
+ }
195
+ }, {
196
+ key: "update",
197
+ value: function update(node) {
198
+ if (!this.nodeIsEqual(node)) {
199
+ return false;
200
+ }
201
+ this.node = node;
202
+ return true;
203
+ }
172
204
  }, {
173
205
  key: "destroy",
174
206
  value: function destroy() {
@@ -183,9 +215,4 @@ var MentionNodeView = /*#__PURE__*/function () {
183
215
  (_this$removeProfileCa = this.removeProfileCard) === null || _this$removeProfileCa === void 0 || _this$removeProfileCa.call(this);
184
216
  }
185
217
  }]);
186
- }();
187
- export var mentionNodeView = function mentionNodeView(config) {
188
- return function (node) {
189
- return new MentionNodeView(node, config);
190
- };
191
- };
218
+ }();
@@ -14,6 +14,9 @@ export var profileCardRenderer = function profileCardRenderer(_ref) {
14
14
  var cleanupSelection;
15
15
  var removeProfileCard = function removeProfileCard() {
16
16
  var _cleanupSelection;
17
+ if (dom instanceof HTMLElement) {
18
+ dom.setAttribute('aria-expanded', 'false');
19
+ }
17
20
  portalProviderAPI.remove(key);
18
21
  renderingProfileCard = false;
19
22
  (_cleanupSelection = cleanupSelection) === null || _cleanupSelection === void 0 || _cleanupSelection();
@@ -23,6 +26,7 @@ export var profileCardRenderer = function profileCardRenderer(_ref) {
23
26
  listener: function listener() {
24
27
  if (dom instanceof HTMLElement && options !== null && options !== void 0 && options.profilecardProvider && !renderingProfileCard) {
25
28
  var _api$selection;
29
+ dom.setAttribute('aria-expanded', 'true');
26
30
  renderingProfileCard = true;
27
31
  portalProviderAPI.render(function () {
28
32
  return /*#__PURE__*/React.createElement(ProfileCardComponent, {
@@ -10,7 +10,7 @@ import { ComponentNames } from '@atlaskit/mention/types';
10
10
  import { fg } from '@atlaskit/platform-feature-flags';
11
11
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
12
12
  import { MentionNodeView } from '../nodeviews/mention';
13
- import { mentionNodeView } from '../nodeviews/mentionNodeView';
13
+ import { MentionNodeView as VanillaMentionNodeView } from '../nodeviews/mentionNodeView';
14
14
  import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types';
15
15
  import { mentionPluginKey } from './key';
16
16
  import { canMentionBeCreatedInRange } from './utils';
@@ -18,7 +18,7 @@ export var ACTIONS = {
18
18
  SET_PROVIDER: 'SET_PROVIDER'
19
19
  };
20
20
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
21
- var PACKAGE_VERSION = "4.3.2";
21
+ var PACKAGE_VERSION = "4.4.0";
22
22
  var setProvider = function setProvider(provider) {
23
23
  return function (state, dispatch) {
24
24
  if (dispatch) {
@@ -94,11 +94,13 @@ export function createMentionPlugin(_ref) {
94
94
  props: {
95
95
  nodeViews: {
96
96
  mention: function mention(node, view, getPos, decorations, innerDecorations) {
97
- return editorExperiment('platform_editor_vanilla_dom', true) ? mentionNodeView({
97
+ return editorExperiment('platform_editor_vanilla_dom', true, {
98
+ exposure: true
99
+ }) ? new VanillaMentionNodeView(node, {
98
100
  options: options,
99
101
  api: api,
100
102
  portalProviderAPI: pmPluginFactoryParams.portalProviderAPI
101
- })(node, view, getPos, decorations, innerDecorations) : getInlineNodeViewProducer({
103
+ }) : getInlineNodeViewProducer({
102
104
  pmPluginFactoryParams: pmPluginFactoryParams,
103
105
  Component: MentionNodeView,
104
106
  extraComponentProps: {
@@ -1,2 +1,8 @@
1
1
  export var MENTION_PROVIDER_REJECTED = 'REJECTED';
2
- export var MENTION_PROVIDER_UNDEFINED = 'UNDEFINED';
2
+ export var MENTION_PROVIDER_UNDEFINED = 'UNDEFINED';
3
+
4
+ /**
5
+ * @private
6
+ * @deprecated Use {@link MentionsPluginOptions} instead.
7
+ * @see https://product-fabric.atlassian.net/browse/ED-27496
8
+ */
@@ -1,6 +1,8 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
2
  import React from 'react';
2
3
  import { Popper as ReactPopper } from '@atlaskit/popper';
3
4
  import Portal from '@atlaskit/portal';
5
+ import { useFocusTrap } from './useFocusTrap';
4
6
  /**
5
7
  * A popup wrapper to match the behaviour of `@atlaskit/popup`
6
8
  *
@@ -15,21 +17,35 @@ import Portal from '@atlaskit/portal';
15
17
  export function Popup(_ref) {
16
18
  var referenceElement = _ref.referenceElement,
17
19
  children = _ref.children;
20
+ var _React$useState = React.useState(null),
21
+ _React$useState2 = _slicedToArray(_React$useState, 2),
22
+ targetRef = _React$useState2[0],
23
+ setPopupRef = _React$useState2[1];
24
+ useFocusTrap({
25
+ targetRef: targetRef
26
+ });
18
27
  return /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement(ReactPopper, {
19
28
  referenceElement: referenceElement,
20
29
  offset: [0, 8],
21
30
  placement: "bottom-end",
22
31
  strategy: "fixed"
23
32
  }, function (_ref2) {
24
- var ref = _ref2.ref,
33
+ var _ref3 = _ref2.ref,
25
34
  style = _ref2.style;
26
- return (
27
- /*#__PURE__*/
35
+ return /*#__PURE__*/React.createElement("div", {
36
+ ref: function ref(node) {
37
+ if (node) {
38
+ if (typeof _ref3 === 'function') {
39
+ _ref3(node);
40
+ } else {
41
+ _ref3.current = node;
42
+ }
43
+ setPopupRef(node);
44
+ }
45
+ }
28
46
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
29
- React.createElement("div", {
30
- ref: ref,
31
- style: style
32
- }, children)
33
- );
47
+ ,
48
+ style: style
49
+ }, children);
34
50
  }));
35
51
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Custom hook to add focus trap
3
+ * used for focus trap in ReactionPicker
4
+ * copied from useFocusManager in @atlaskit/popup
5
+ */
6
+ import { useEffect } from 'react';
7
+ import createFocusTrap from 'focus-trap';
8
+ export var useFocusTrap = function useFocusTrap(_ref) {
9
+ var targetRef = _ref.targetRef;
10
+ useEffect(function () {
11
+ if (!targetRef) {
12
+ return;
13
+ }
14
+ var trapConfig = {
15
+ clickOutsideDeactivates: true,
16
+ escapeDeactivates: true,
17
+ initialFocus: targetRef,
18
+ fallbackFocus: targetRef,
19
+ returnFocusOnDeactivate: true
20
+ };
21
+ var focusTrap = createFocusTrap(targetRef, trapConfig);
22
+
23
+ // wait for the popup to reposition itself before we focus
24
+ var frameId = requestAnimationFrame(function () {
25
+ frameId = null;
26
+ focusTrap.activate();
27
+ });
28
+ return function () {
29
+ if (frameId !== null) {
30
+ cancelAnimationFrame(frameId);
31
+ frameId = null;
32
+ }
33
+ focusTrap.deactivate();
34
+ };
35
+ }, [targetRef]);
36
+ };
@@ -1,3 +1,3 @@
1
1
  export { mentionsPlugin } from './mentionsPlugin';
2
2
  export type { MentionsPlugin } from './mentionsPluginType';
3
- export type { MentionPluginConfig, MentionPluginOptions, MentionSharedState } from './types';
3
+ export type { MentionPluginConfig, MentionPluginOptions, MentionsPluginOptions, MentionSharedState, } from './types';
@@ -1,6 +1,7 @@
1
- import type { NodeViewConstructor } from '@atlaskit/editor-common/lazy-node-view';
2
1
  import { type PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
2
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
4
+ import type { NodeView } from '@atlaskit/editor-prosemirror/view';
4
5
  import type { MentionsPlugin } from '../mentionsPluginType';
5
6
  import { type MentionPluginOptions } from '../types';
6
7
  interface MentionNodeViewProps {
@@ -8,5 +9,24 @@ interface MentionNodeViewProps {
8
9
  api: ExtractInjectionAPI<MentionsPlugin> | undefined;
9
10
  portalProviderAPI: PortalProviderAPI;
10
11
  }
11
- export declare const mentionNodeView: (config: MentionNodeViewProps) => NodeViewConstructor;
12
+ export declare class MentionNodeView implements NodeView {
13
+ private state;
14
+ dom: Node;
15
+ domElement: HTMLElement | undefined;
16
+ contentDOM: HTMLElement | undefined;
17
+ private config;
18
+ private node;
19
+ private cleanup;
20
+ private destroyProfileCard;
21
+ private removeProfileCard;
22
+ private mentionPrimitiveElement;
23
+ constructor(node: PMNode, config: MentionNodeViewProps);
24
+ private setClassList;
25
+ private setTextContent;
26
+ private updateState;
27
+ private nodeIsEqual;
28
+ update(node: PMNode): boolean;
29
+ destroy(): void;
30
+ deselectNode(): void;
31
+ }
12
32
  export {};
@@ -5,7 +5,7 @@ import type { MentionsPlugin } from '../mentionsPluginType';
5
5
  import { type MentionPluginOptions } from '../types';
6
6
  export declare const profileCardRenderer: ({ dom, options, portalProviderAPI, node, api, }: {
7
7
  dom: Node;
8
- options?: MentionPluginOptions | undefined;
8
+ options?: import("../types").MentionsPluginOptions | undefined;
9
9
  portalProviderAPI: PortalProviderAPI;
10
10
  node: PMNode;
11
11
  api: ExtractInjectionAPI<MentionsPlugin> | undefined;
@@ -15,7 +15,7 @@ export interface MentionPluginConfig {
15
15
  insertDisplayName?: boolean;
16
16
  profilecardProvider?: Promise<ProfilecardProvider>;
17
17
  }
18
- export interface MentionPluginOptions extends MentionPluginConfig {
18
+ export interface MentionsPluginOptions extends MentionPluginConfig {
19
19
  mentionProvider?: Providers['mentionProvider'];
20
20
  sanitizePrivateContent?: boolean;
21
21
  allowZeroWidthSpaceAfter?: boolean;
@@ -26,6 +26,12 @@ export interface MentionPluginOptions extends MentionPluginConfig {
26
26
  taskLocalId?: string;
27
27
  }[]) => void;
28
28
  }
29
+ /**
30
+ * @private
31
+ * @deprecated Use {@link MentionsPluginOptions} instead.
32
+ * @see https://product-fabric.atlassian.net/browse/ED-27496
33
+ */
34
+ export type MentionPluginOptions = MentionsPluginOptions;
29
35
  export type MentionPluginState = {
30
36
  mentionProvider?: MentionProvider;
31
37
  mentions?: Array<MentionDescription>;
@@ -0,0 +1,4 @@
1
+ export type FocusManagerHook = {
2
+ targetRef: HTMLDivElement | null;
3
+ };
4
+ export declare const useFocusTrap: ({ targetRef }: FocusManagerHook) => void;
@@ -1,3 +1,3 @@
1
1
  export { mentionsPlugin } from './mentionsPlugin';
2
2
  export type { MentionsPlugin } from './mentionsPluginType';
3
- export type { MentionPluginConfig, MentionPluginOptions, MentionSharedState } from './types';
3
+ export type { MentionPluginConfig, MentionPluginOptions, MentionsPluginOptions, MentionSharedState, } from './types';
@@ -1,6 +1,7 @@
1
- import type { NodeViewConstructor } from '@atlaskit/editor-common/lazy-node-view';
2
1
  import { type PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
2
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
4
+ import type { NodeView } from '@atlaskit/editor-prosemirror/view';
4
5
  import type { MentionsPlugin } from '../mentionsPluginType';
5
6
  import { type MentionPluginOptions } from '../types';
6
7
  interface MentionNodeViewProps {
@@ -8,5 +9,24 @@ interface MentionNodeViewProps {
8
9
  api: ExtractInjectionAPI<MentionsPlugin> | undefined;
9
10
  portalProviderAPI: PortalProviderAPI;
10
11
  }
11
- export declare const mentionNodeView: (config: MentionNodeViewProps) => NodeViewConstructor;
12
+ export declare class MentionNodeView implements NodeView {
13
+ private state;
14
+ dom: Node;
15
+ domElement: HTMLElement | undefined;
16
+ contentDOM: HTMLElement | undefined;
17
+ private config;
18
+ private node;
19
+ private cleanup;
20
+ private destroyProfileCard;
21
+ private removeProfileCard;
22
+ private mentionPrimitiveElement;
23
+ constructor(node: PMNode, config: MentionNodeViewProps);
24
+ private setClassList;
25
+ private setTextContent;
26
+ private updateState;
27
+ private nodeIsEqual;
28
+ update(node: PMNode): boolean;
29
+ destroy(): void;
30
+ deselectNode(): void;
31
+ }
12
32
  export {};
@@ -5,7 +5,7 @@ import type { MentionsPlugin } from '../mentionsPluginType';
5
5
  import { type MentionPluginOptions } from '../types';
6
6
  export declare const profileCardRenderer: ({ dom, options, portalProviderAPI, node, api, }: {
7
7
  dom: Node;
8
- options?: MentionPluginOptions | undefined;
8
+ options?: import("../types").MentionsPluginOptions | undefined;
9
9
  portalProviderAPI: PortalProviderAPI;
10
10
  node: PMNode;
11
11
  api: ExtractInjectionAPI<MentionsPlugin> | undefined;
@@ -15,7 +15,7 @@ export interface MentionPluginConfig {
15
15
  insertDisplayName?: boolean;
16
16
  profilecardProvider?: Promise<ProfilecardProvider>;
17
17
  }
18
- export interface MentionPluginOptions extends MentionPluginConfig {
18
+ export interface MentionsPluginOptions extends MentionPluginConfig {
19
19
  mentionProvider?: Providers['mentionProvider'];
20
20
  sanitizePrivateContent?: boolean;
21
21
  allowZeroWidthSpaceAfter?: boolean;
@@ -26,6 +26,12 @@ export interface MentionPluginOptions extends MentionPluginConfig {
26
26
  taskLocalId?: string;
27
27
  }[]) => void;
28
28
  }
29
+ /**
30
+ * @private
31
+ * @deprecated Use {@link MentionsPluginOptions} instead.
32
+ * @see https://product-fabric.atlassian.net/browse/ED-27496
33
+ */
34
+ export type MentionPluginOptions = MentionsPluginOptions;
29
35
  export type MentionPluginState = {
30
36
  mentionProvider?: MentionProvider;
31
37
  mentions?: Array<MentionDescription>;
@@ -0,0 +1,4 @@
1
+ export type FocusManagerHook = {
2
+ targetRef: HTMLDivElement | null;
3
+ };
4
+ export declare const useFocusTrap: ({ targetRef }: FocusManagerHook) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-mentions",
3
- "version": "4.3.2",
3
+ "version": "4.4.0",
4
4
  "description": "Mentions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -35,10 +35,10 @@
35
35
  "dependencies": {
36
36
  "@atlaskit/adf-schema": "^47.6.0",
37
37
  "@atlaskit/css": "^0.10.0",
38
- "@atlaskit/editor-common": "^103.0.0",
38
+ "@atlaskit/editor-common": "^103.4.0",
39
39
  "@atlaskit/editor-plugin-analytics": "^2.2.0",
40
40
  "@atlaskit/editor-plugin-base": "^2.3.0",
41
- "@atlaskit/editor-plugin-context-identifier": "^2.0.0",
41
+ "@atlaskit/editor-plugin-context-identifier": "^2.1.0",
42
42
  "@atlaskit/editor-plugin-selection": "^2.1.0",
43
43
  "@atlaskit/editor-plugin-type-ahead": "^2.3.0",
44
44
  "@atlaskit/editor-prosemirror": "7.0.0",
@@ -54,6 +54,7 @@
54
54
  "@babel/runtime": "^7.0.0",
55
55
  "@compiled/react": "^0.18.3",
56
56
  "bind-event-listener": "^3.0.0",
57
+ "focus-trap": "^2.4.5",
57
58
  "uuid": "^3.1.0"
58
59
  },
59
60
  "peerDependencies": {