@atlaskit/editor-plugin-type-ahead 22.0.3 → 22.1.1

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/cjs/ui/ListRow.js +4 -2
  3. package/dist/cjs/ui/SkillTagLabel.compiled.css +19 -0
  4. package/dist/cjs/ui/SkillTagLabel.js +88 -0
  5. package/dist/cjs/ui/TypeAheadListItem.js +10 -2
  6. package/dist/cjs/ui/registered-menu/RegisteredTypeAheadMenu.compiled.css +3 -2
  7. package/dist/cjs/ui/registered-menu/RegisteredTypeAheadMenu.js +22 -7
  8. package/dist/cjs/ui/registered-menu/TypeAheadMenuRenderer.js +9 -2
  9. package/dist/cjs/ui/registered-menu/createTypeAheadRowRenderer.js +2 -0
  10. package/dist/es2019/ui/ListRow.js +6 -2
  11. package/dist/es2019/ui/SkillTagLabel.compiled.css +19 -0
  12. package/dist/es2019/ui/SkillTagLabel.js +72 -0
  13. package/dist/es2019/ui/TypeAheadListItem.js +9 -2
  14. package/dist/es2019/ui/registered-menu/RegisteredTypeAheadMenu.compiled.css +3 -2
  15. package/dist/es2019/ui/registered-menu/RegisteredTypeAheadMenu.js +21 -8
  16. package/dist/es2019/ui/registered-menu/TypeAheadMenuRenderer.js +10 -2
  17. package/dist/es2019/ui/registered-menu/createTypeAheadRowRenderer.js +2 -0
  18. package/dist/esm/ui/ListRow.js +4 -2
  19. package/dist/esm/ui/SkillTagLabel.compiled.css +19 -0
  20. package/dist/esm/ui/SkillTagLabel.js +79 -0
  21. package/dist/esm/ui/TypeAheadListItem.js +11 -2
  22. package/dist/esm/ui/registered-menu/RegisteredTypeAheadMenu.compiled.css +3 -2
  23. package/dist/esm/ui/registered-menu/RegisteredTypeAheadMenu.js +23 -8
  24. package/dist/esm/ui/registered-menu/TypeAheadMenuRenderer.js +9 -2
  25. package/dist/esm/ui/registered-menu/createTypeAheadRowRenderer.js +2 -0
  26. package/dist/types/ui/ListRow.d.ts +1 -0
  27. package/dist/types/ui/SkillTagLabel.d.ts +21 -0
  28. package/dist/types/ui/registered-menu/createTypeAheadRowRenderer.d.ts +2 -1
  29. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @atlaskit/editor-plugin-type-ahead
2
2
 
3
+ ## 22.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`7306003a7565b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7306003a7565b) -
8
+ Fix modal dismissal, category spacing, measured list height, and viewport-aware menu placement
9
+ under platform_editor_slash_command.
10
+ - Updated dependencies
11
+
12
+ ## 22.1.0
13
+
14
+ ### Minor Changes
15
+
16
+ - [`4c2cee2609bfd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4c2cee2609bfd) -
17
+ Render Rovo skill quick-insert items as a slash-command tag (`/slug`) in the editor, behind the
18
+ display_skill_lozenge_in_editor experiment.
19
+
20
+ ### Patch Changes
21
+
22
+ - [`4af80d911cc15`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4af80d911cc15) -
23
+ Refresh open slash-command menus when Skills and other provider items load under
24
+ platform_editor_slash_command.
25
+
3
26
  ## 22.0.3
4
27
 
5
28
  ### Patch Changes
@@ -24,6 +24,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
24
24
  var ListRow = exports.ListRow = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
25
25
  var children = _ref.children,
26
26
  measure = _ref.measure,
27
+ onMeasured = _ref.onMeasured,
27
28
  index = _ref.index,
28
29
  style = _ref.style,
29
30
  isVisible = _ref.isVisible,
@@ -36,13 +37,14 @@ var ListRow = exports.ListRow = /*#__PURE__*/(0, _react.forwardRef)(function (_r
36
37
  return;
37
38
  }
38
39
  var observer = new ResizeObserver(function () {
39
- return measure();
40
+ measure();
41
+ onMeasured === null || onMeasured === void 0 || onMeasured();
40
42
  });
41
43
  observer.observe(childElementRef.current);
42
44
  return function () {
43
45
  return observer.disconnect();
44
46
  };
45
- }, [isScrolling, isVisible, measure]);
47
+ }, [isScrolling, isVisible, measure, onMeasured]);
46
48
  return (
47
49
  /*#__PURE__*/
48
50
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
@@ -0,0 +1,19 @@
1
+ ._2rkolb4i{border-radius:var(--ds-radius-xsmall,2px)}._16d9qvcn{-webkit-box-decoration-break:clone;box-decoration-break:clone}
2
+ ._18u01b66{margin-left:var(--ds-space-050,4px)}
3
+ ._19bv1b66{padding-left:var(--ds-space-050,4px)}
4
+ ._1e0c1nu9{display:inline}
5
+ ._2hwx1b66{margin-right:var(--ds-space-050,4px)}
6
+ ._bfhki8nm{background-color:var(--ds-background-neutral,#0515240f)}
7
+ ._syaz16jw{color:var(--ds-text-accent-blue,#1558bc)}
8
+ ._syaz17qg{color:var(--ds-text-accent-teal,#206a83)}
9
+ ._syaz1s8m{color:var(--ds-text-accent-magenta,#943d73)}
10
+ ._syaz1sqi{color:var(--ds-text-accent-gray,#505258)}
11
+ ._syaz1tco{color:var(--ds-text-accent-lime,#4c6b1f)}
12
+ ._syaz9lu1{color:var(--ds-text-accent-red,#ae2e24)}
13
+ ._syazazsu{color:var(--ds-text-subtle,#505258)}
14
+ ._syazfb2s{color:var(--ds-text-accent-yellow,#7f5f01)}
15
+ ._syazh55r{color:var(--ds-text-accent-green,#216e4e)}
16
+ ._syazp1lv{color:var(--ds-text-accent-orange,#9e4c00)}
17
+ ._syazqmo9{color:var(--ds-text-accent-purple,#803fa5)}
18
+ ._u5f31b66{padding-right:var(--ds-space-050,4px)}
19
+ ._vchhusvi{box-sizing:border-box}
@@ -0,0 +1,88 @@
1
+ /* SkillTagLabel.tsx generated by @compiled/babel-plugin v3.0.2 */
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ exports.parseSkillTagTitle = exports.SkillTagLabel = void 0;
10
+ require("./SkillTagLabel.compiled.css");
11
+ var React = _interopRequireWildcard(require("react"));
12
+ var _runtime = require("@compiled/react/runtime");
13
+ var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
14
+ var _css = require("@atlaskit/css");
15
+ var _box = require("@atlaskit/primitives/compiled/box");
16
+ var _text = require("@atlaskit/primitives/compiled/text");
17
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
18
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
19
+ var SKILL_TITLE_PREFIX = 'skill::';
20
+ /**
21
+ * Parses a quick-insert item title of the form `skill::{COLOR}::{SLUG}::{NAME}`, produced by the
22
+ * Rovo skills quick-insert manifest when `display_skill_lozenge_in_editor` is enabled. Returns
23
+ * undefined for any title that isn't in this format.
24
+ */
25
+ var parseSkillTagTitle = exports.parseSkillTagTitle = function parseSkillTagTitle(title) {
26
+ if (!title.startsWith(SKILL_TITLE_PREFIX)) {
27
+ return undefined;
28
+ }
29
+ var _title$split = title.split('::'),
30
+ _title$split2 = (0, _toArray2.default)(_title$split),
31
+ color = _title$split2[1],
32
+ slug = _title$split2[2],
33
+ nameParts = _arrayLikeToArray(_title$split2).slice(3);
34
+ var name = nameParts.join('::');
35
+ if (!slug || !name) {
36
+ return undefined;
37
+ }
38
+ return {
39
+ color: color || undefined,
40
+ slug: slug,
41
+ name: name
42
+ };
43
+ };
44
+ var styles = {
45
+ tag: "_2rkolb4i _1e0c1nu9 _16d9qvcn _vchhusvi _18u01b66 _19bv1b66 _u5f31b66 _bfhki8nm",
46
+ slash: "_1e0c1nu9 _2hwx1b66"
47
+ };
48
+
49
+ // Slash accent colors for a Rovo skill, mirroring the enum used by the inserted skill chip
50
+ // (@atlassian/rovo-platform-ui-components/skills/skill-colors). Duplicated here — rather than
51
+ // imported — so this shared, product-agnostic editor package doesn't take on a dependency on an
52
+ // ai-mate/Rovo UI package. Modelled as a finite cssMap (rather than a runtime style override) so
53
+ // each color resolves to a static, ratcheted style.
54
+ var accentColorStyles = {
55
+ LIME: "_syaz1tco",
56
+ RED: "_syaz9lu1",
57
+ ORANGE: "_syazp1lv",
58
+ YELLOW: "_syazfb2s",
59
+ GREEN: "_syazh55r",
60
+ TEAL: "_syaz17qg",
61
+ BLUE: "_syaz16jw",
62
+ PURPLE: "_syazqmo9",
63
+ MAGENTA: "_syaz1s8m",
64
+ GRAY: "_syaz1sqi",
65
+ DEFAULT: "_syazazsu"
66
+ };
67
+ var isAccentColor = function isAccentColor(color) {
68
+ return Boolean(color && color in accentColorStyles);
69
+ };
70
+ /**
71
+ * Renders a skill as a tag/chip label in the quick-insert typeahead list, instead of plain text,
72
+ * mirroring the "/" + slug layout of the inserted skill chip (SkillTag). Never shows a hovercard
73
+ * — this is a lightweight label for the list row, not the inserted chip.
74
+ */
75
+ var SkillTagLabel = exports.SkillTagLabel = function SkillTagLabel(_ref) {
76
+ var color = _ref.color,
77
+ slug = _ref.slug;
78
+ var accentColor = isAccentColor(color) ? color : 'DEFAULT';
79
+ return /*#__PURE__*/React.createElement(_box.Box, {
80
+ as: "span",
81
+ xcss: styles.tag
82
+ }, /*#__PURE__*/React.createElement(_box.Box, {
83
+ as: "span",
84
+ xcss: (0, _css.cx)(styles.slash, accentColorStyles[accentColor])
85
+ }, "/"), /*#__PURE__*/React.createElement(_text.Text, {
86
+ as: "span"
87
+ }, slug));
88
+ };
@@ -20,6 +20,7 @@ var _shortcut = require("@atlaskit/editor-shared-styles/shortcut");
20
20
  var _buttonItem = _interopRequireDefault(require("@atlaskit/menu/button-item"));
21
21
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
22
22
  var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden/visually-hidden"));
23
+ var _SkillTagLabel = require("./SkillTagLabel");
23
24
  var _templateObject, _templateObject2, _templateObject3, _templateObject4;
24
25
  /**
25
26
  * @jsxRuntime classic
@@ -161,6 +162,7 @@ var CustomItemComponentWrapper = /*#__PURE__*/_react.default.memo(function (prop
161
162
  })));
162
163
  });
163
164
  var TypeAheadListItem = exports.TypeAheadListItem = /*#__PURE__*/_react.default.memo(function (_ref) {
165
+ var _skillTag$name;
164
166
  var item = _ref.item,
165
167
  itemsLength = _ref.itemsLength,
166
168
  selectedIndex = _ref.selectedIndex,
@@ -206,6 +208,9 @@ var TypeAheadListItem = exports.TypeAheadListItem = /*#__PURE__*/_react.default.
206
208
  var icon = item.icon,
207
209
  title = item.title,
208
210
  customRenderItem = item.render;
211
+ var skillTag = (0, _react.useMemo)(function () {
212
+ return (0, _isExperimentEnabled.isExperimentEnabled)('display_skill_lozenge_in_editor') ? (0, _SkillTagLabel.parseSkillTagTitle)(title) : undefined;
213
+ }, [title]);
209
214
  var elementIcon = (0, _react.useMemo)(function () {
210
215
  return (0, _react2.jsx)("div", {
211
216
  css: [itemIcon, moreElementsInQuickInsertViewEnabled && itemIconSizeUpdated]
@@ -264,7 +269,7 @@ var TypeAheadListItem = exports.TypeAheadListItem = /*#__PURE__*/_react.default.
264
269
  iconBefore: elementIcon,
265
270
  isSelected: isSelected,
266
271
  "aria-selected": isSelected,
267
- "aria-label": title,
272
+ "aria-label": (_skillTag$name = skillTag === null || skillTag === void 0 ? void 0 : skillTag.name) !== null && _skillTag$name !== void 0 ? _skillTag$name : title,
268
273
  "aria-describedby": descriptionText || shortcutText ? descriptionId : undefined,
269
274
  "aria-setsize": itemsLength,
270
275
  "aria-posinset": itemIndex + 1,
@@ -283,7 +288,10 @@ var TypeAheadListItem = exports.TypeAheadListItem = /*#__PURE__*/_react.default.
283
288
  css: itemBody
284
289
  }, (0, _react2.jsx)("div", {
285
290
  css: [itemTitle, moreElementsInQuickInsertViewEnabled && itemTitleOverride, itemIsDisabled && disabledStyle, item.lozenge && titleWithLozengeStyle]
286
- }, item.title, item.lozenge && (0, _react2.jsx)("span", {
291
+ }, skillTag ? (0, _react2.jsx)(_SkillTagLabel.SkillTagLabel, {
292
+ color: skillTag.color,
293
+ slug: skillTag.slug
294
+ }) : item.title, item.lozenge && (0, _react2.jsx)("span", {
287
295
  css: lozengeWrapperStyle
288
296
  }, item.lozenge)), (0, _react2.jsx)("div", {
289
297
  css: itemAfter
@@ -1,7 +1,8 @@
1
- ._2rko12b0{border-radius:var(--ds-radius-small,4px)}
2
- ._1rjc1b66{padding-block:var(--ds-space-050,4px)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
1
+ ._2rko1mok{border-radius:var(--ds-radius-large,8px)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
3
2
  ._18m915vq{overflow-y:hidden}
4
3
  ._1bsbnklw{width:20pc}
4
+ ._1q51u2gc{padding-block-start:var(--ds-space-100,8px)}
5
5
  ._1reo15vq{overflow-x:hidden}
6
+ ._85i512x7{padding-block-end:var(--ds-space-075,6px)}
6
7
  ._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
7
8
  ._vchhusvi{box-sizing:border-box}
@@ -14,6 +14,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
14
14
  var _react = _interopRequireWildcard(require("react"));
15
15
  var _reactIntl = require("react-intl");
16
16
  var _registeredMenuModel = require("@atlaskit/editor-common/quick-insert/registered-menu-model");
17
+ var _useMenuPopupSizing = require("@atlaskit/editor-common/quick-insert/use-menu-popup-sizing");
17
18
  var _typeAheadIsSectionOverflowItemKey = require("@atlaskit/editor-common/type-ahead-is-section-overflow-item-key");
18
19
  var _typeAheadSurfaceContext = require("@atlaskit/editor-common/type-ahead-surface-context");
19
20
  var _ui = require("@atlaskit/editor-common/ui");
@@ -28,13 +29,18 @@ var _TypeAheadMenuRenderer = require("./TypeAheadMenuRenderer");
28
29
  var _TypeAheadProvider = require("./TypeAheadProvider");
29
30
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
30
31
  var styles = {
31
- menu: "_2rko12b0 _1reo15vq _18m915vq _1rjc1b66 _bfhk1bhr _vchhusvi _16qs130s _1bsbnklw"
32
+ menu: "_2rko1mok _1reo15vq _18m915vq _bfhk1bhr _vchhusvi _16qs130s _1q51u2gc _85i512x7 _1bsbnklw"
32
33
  };
33
34
  var DEFAULT_MENU_MAX_HEIGHT = 480;
34
- var MENU_VERTICAL_PADDING = 8;
35
+ var MENU_VERTICAL_PADDING = 14;
35
36
  var MENU_WIDTH = 320;
36
37
  var POPUP_OFFSET = [0, 8];
38
+ var EMPTY_COMPONENTS = [];
39
+ var subscribeToNothing = function subscribeToNothing() {
40
+ return function () {};
41
+ };
37
42
  var RegisteredTypeAheadMenu = exports.RegisteredTypeAheadMenu = function RegisteredTypeAheadMenu(_ref) {
43
+ var _api$uiControlRegistr2, _api$uiControlRegistr3;
38
44
  var anchorElement = _ref.anchorElement,
39
45
  api = _ref.api,
40
46
  cancel = _ref.cancel,
@@ -52,6 +58,13 @@ var RegisteredTypeAheadMenu = exports.RegisteredTypeAheadMenu = function Registe
52
58
  setQuery = _ref.setQuery,
53
59
  surface = _ref.surface,
54
60
  triggerHandler = _ref.triggerHandler;
61
+ var menuHeight = (0, _useMenuPopupSizing.useMenuPopupSizing)({
62
+ target: anchorElement,
63
+ boundariesElement: popupsBoundariesElement,
64
+ scrollableElement: popupsScrollableElement,
65
+ maxHeight: maxHeight,
66
+ offset: POPUP_OFFSET[1]
67
+ });
55
68
  var _useIntl = (0, _reactIntl.useIntl)(),
56
69
  formatMessage = _useIntl.formatMessage;
57
70
  var generatedId = (0, _react.useId)();
@@ -71,10 +84,12 @@ var RegisteredTypeAheadMenu = exports.RegisteredTypeAheadMenu = function Registe
71
84
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
72
85
  selectedItemIndex = _useState4[0],
73
86
  setSelectedItemIndex = _useState4[1];
74
- var components = (0, _react.useMemo)(function () {
75
- var _api$uiControlRegistr, _api$uiControlRegistr2;
76
- return (_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(surface.root.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
87
+ var getComponents = (0, _react.useCallback)(function () {
88
+ var _api$uiControlRegistr;
89
+ var components = api === null || api === void 0 || (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 ? void 0 : _api$uiControlRegistr.actions.getComponents(surface.root.key);
90
+ return components !== null && components !== void 0 && components.length ? components : EMPTY_COMPONENTS;
77
91
  }, [api, surface.root.key]);
92
+ var components = (0, _react.useSyncExternalStore)((_api$uiControlRegistr2 = api === null || api === void 0 || (_api$uiControlRegistr3 = api.uiControlRegistry) === null || _api$uiControlRegistr3 === void 0 ? void 0 : _api$uiControlRegistr3.actions.subscribe) !== null && _api$uiControlRegistr2 !== void 0 ? _api$uiControlRegistr2 : subscribeToNothing, getComponents, getComponents);
78
93
  var isSlashCommandEnabled = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_slash_command');
79
94
  var hasSectionOverflowItems = (0, _react.useMemo)(function () {
80
95
  return components.some(function (_ref2) {
@@ -165,7 +180,7 @@ var RegisteredTypeAheadMenu = exports.RegisteredTypeAheadMenu = function Registe
165
180
  }), /*#__PURE__*/_react.default.createElement(_ui.Popup, {
166
181
  ariaLabel: null,
167
182
  boundariesElement: popupsBoundariesElement,
168
- fitHeight: maxHeight,
183
+ fitHeight: menuHeight,
169
184
  fitWidth: MENU_WIDTH,
170
185
  mountTo: popupsMountPoint,
171
186
  offset: POPUP_OFFSET,
@@ -184,7 +199,7 @@ var RegisteredTypeAheadMenu = exports.RegisteredTypeAheadMenu = function Registe
184
199
  Item: surface.Item,
185
200
  listLabel: surface.listLabel,
186
201
  listId: listId,
187
- maxHeight: Math.max(0, maxHeight - MENU_VERTICAL_PADDING),
202
+ maxHeight: Math.max(0, menuHeight - MENU_VERTICAL_PADDING),
188
203
  model: menuModel,
189
204
  onItemHover: setSelectedItemIndex,
190
205
  selectedItemIndex: selectedItemIndex
@@ -12,6 +12,7 @@ var _react = _interopRequireWildcard(require("react"));
12
12
  var _reactIntl = require("react-intl");
13
13
  var _CellMeasurer = require("react-virtualized/dist/commonjs/CellMeasurer");
14
14
  var _List = require("react-virtualized/dist/commonjs/List");
15
+ var _useMenuListHeight2 = require("@atlaskit/editor-common/quick-insert/use-menu-list-height");
15
16
  var _typeAhead = require("@atlaskit/editor-common/type-ahead");
16
17
  var _compiled = require("@atlaskit/primitives/compiled");
17
18
  var _createTypeAheadRowRenderer = require("./createTypeAheadRowRenderer");
@@ -24,7 +25,8 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
24
25
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
25
26
  var LIST_WIDTH = 320;
26
27
  var ESTIMATED_ROW_HEIGHT = 56;
27
- var MENU_FOOTER_HEIGHT = 48;
28
+ // 40px item + 8px block padding + 1px separator.
29
+ var MENU_FOOTER_HEIGHT = 49;
28
30
  var TypeAheadMenuRenderer = exports.TypeAheadMenuRenderer = function TypeAheadMenuRenderer(_ref) {
29
31
  var _model$root$component;
30
32
  var Item = _ref.Item,
@@ -82,6 +84,9 @@ var TypeAheadMenuRenderer = exports.TypeAheadMenuRenderer = function TypeAheadMe
82
84
  return "".concat(type, ":").concat(key);
83
85
  }).join('\0');
84
86
  }, [rows]);
87
+ var _useMenuListHeight = (0, _useMenuListHeight2.useMenuListHeight)(cache, rows.length, rowKeySignature),
88
+ measuredHeight = _useMenuListHeight.height,
89
+ updateHeight = _useMenuListHeight.updateHeight;
85
90
  (0, _react.useLayoutEffect)(function () {
86
91
  var _listRef$current, _listRef$current2;
87
92
  cache.clearAll();
@@ -96,6 +101,7 @@ var TypeAheadMenuRenderer = exports.TypeAheadMenuRenderer = function TypeAheadMe
96
101
  }, [selectedRowIndex]);
97
102
  var renderRow = (0, _createTypeAheadRowRenderer.createTypeAheadRowRenderer)({
98
103
  cache: cache,
104
+ onMeasured: updateHeight,
99
105
  itemIndexByRowIndex: itemIndexByRowIndex,
100
106
  Item: Item,
101
107
  listId: listId,
@@ -119,7 +125,8 @@ var TypeAheadMenuRenderer = exports.TypeAheadMenuRenderer = function TypeAheadMe
119
125
  role: hasListboxContent ? 'listbox' : undefined
120
126
  }, rows.length > 0 ? /*#__PURE__*/_react.default.createElement(_List.List, {
121
127
  containerRole: "presentation",
122
- height: Math.min(rows.length * ESTIMATED_ROW_HEIGHT, listMaxHeight),
128
+ height: Math.min(measuredHeight, listMaxHeight),
129
+ onRowsRendered: updateHeight,
123
130
  overscanRowCount: 3,
124
131
  ref: listRef,
125
132
  role: "presentation",
@@ -13,6 +13,7 @@ var _TypeAheadSectionRow = require("./TypeAheadSectionRow");
13
13
  var noOp = function noOp() {};
14
14
  var createTypeAheadRowRenderer = exports.createTypeAheadRowRenderer = function createTypeAheadRowRenderer(_ref) {
15
15
  var cache = _ref.cache,
16
+ onMeasured = _ref.onMeasured,
16
17
  itemIndexByRowIndex = _ref.itemIndexByRowIndex,
17
18
  Item = _ref.Item,
18
19
  listId = _ref.listId,
@@ -44,6 +45,7 @@ var createTypeAheadRowRenderer = exports.createTypeAheadRowRenderer = function c
44
45
  isScrolling: isScrolling,
45
46
  isVisible: isVisible,
46
47
  measure: measure,
48
+ onMeasured: onMeasured,
47
49
  onMouseMove: noOp,
48
50
  style: style
49
51
  }, registration.type === 'menu-section' ? /*#__PURE__*/_react.default.createElement(_TypeAheadSectionRow.TypeAheadSectionRow, {
@@ -16,6 +16,7 @@ import React, { useEffect, useRef, forwardRef } from 'react';
16
16
  export const ListRow = /*#__PURE__*/forwardRef(({
17
17
  children,
18
18
  measure,
19
+ onMeasured,
19
20
  index,
20
21
  style,
21
22
  isVisible,
@@ -28,10 +29,13 @@ export const ListRow = /*#__PURE__*/forwardRef(({
28
29
  if (!childElementRef.current || !isVisible || isScrolling) {
29
30
  return;
30
31
  }
31
- const observer = new ResizeObserver(() => measure());
32
+ const observer = new ResizeObserver(() => {
33
+ measure();
34
+ onMeasured === null || onMeasured === void 0 ? void 0 : onMeasured();
35
+ });
32
36
  observer.observe(childElementRef.current);
33
37
  return () => observer.disconnect();
34
- }, [isScrolling, isVisible, measure]);
38
+ }, [isScrolling, isVisible, measure, onMeasured]);
35
39
  return (
36
40
  /*#__PURE__*/
37
41
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
@@ -0,0 +1,19 @@
1
+ ._2rkolb4i{border-radius:var(--ds-radius-xsmall,2px)}._16d9qvcn{-webkit-box-decoration-break:clone;box-decoration-break:clone}
2
+ ._18u01b66{margin-left:var(--ds-space-050,4px)}
3
+ ._19bv1b66{padding-left:var(--ds-space-050,4px)}
4
+ ._1e0c1nu9{display:inline}
5
+ ._2hwx1b66{margin-right:var(--ds-space-050,4px)}
6
+ ._bfhki8nm{background-color:var(--ds-background-neutral,#0515240f)}
7
+ ._syaz16jw{color:var(--ds-text-accent-blue,#1558bc)}
8
+ ._syaz17qg{color:var(--ds-text-accent-teal,#206a83)}
9
+ ._syaz1s8m{color:var(--ds-text-accent-magenta,#943d73)}
10
+ ._syaz1sqi{color:var(--ds-text-accent-gray,#505258)}
11
+ ._syaz1tco{color:var(--ds-text-accent-lime,#4c6b1f)}
12
+ ._syaz9lu1{color:var(--ds-text-accent-red,#ae2e24)}
13
+ ._syazazsu{color:var(--ds-text-subtle,#505258)}
14
+ ._syazfb2s{color:var(--ds-text-accent-yellow,#7f5f01)}
15
+ ._syazh55r{color:var(--ds-text-accent-green,#216e4e)}
16
+ ._syazp1lv{color:var(--ds-text-accent-orange,#9e4c00)}
17
+ ._syazqmo9{color:var(--ds-text-accent-purple,#803fa5)}
18
+ ._u5f31b66{padding-right:var(--ds-space-050,4px)}
19
+ ._vchhusvi{box-sizing:border-box}
@@ -0,0 +1,72 @@
1
+ /* SkillTagLabel.tsx generated by @compiled/babel-plugin v3.0.2 */
2
+ import "./SkillTagLabel.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { cx } from '@atlaskit/css';
6
+ import { Box } from '@atlaskit/primitives/compiled/box';
7
+ import { Text } from '@atlaskit/primitives/compiled/text';
8
+ const SKILL_TITLE_PREFIX = 'skill::';
9
+ /**
10
+ * Parses a quick-insert item title of the form `skill::{COLOR}::{SLUG}::{NAME}`, produced by the
11
+ * Rovo skills quick-insert manifest when `display_skill_lozenge_in_editor` is enabled. Returns
12
+ * undefined for any title that isn't in this format.
13
+ */
14
+ export const parseSkillTagTitle = title => {
15
+ if (!title.startsWith(SKILL_TITLE_PREFIX)) {
16
+ return undefined;
17
+ }
18
+ const [, color, slug, ...nameParts] = title.split('::');
19
+ const name = nameParts.join('::');
20
+ if (!slug || !name) {
21
+ return undefined;
22
+ }
23
+ return {
24
+ color: color || undefined,
25
+ slug,
26
+ name
27
+ };
28
+ };
29
+ const styles = {
30
+ tag: "_2rkolb4i _1e0c1nu9 _16d9qvcn _vchhusvi _18u01b66 _19bv1b66 _u5f31b66 _bfhki8nm",
31
+ slash: "_1e0c1nu9 _2hwx1b66"
32
+ };
33
+
34
+ // Slash accent colors for a Rovo skill, mirroring the enum used by the inserted skill chip
35
+ // (@atlassian/rovo-platform-ui-components/skills/skill-colors). Duplicated here — rather than
36
+ // imported — so this shared, product-agnostic editor package doesn't take on a dependency on an
37
+ // ai-mate/Rovo UI package. Modelled as a finite cssMap (rather than a runtime style override) so
38
+ // each color resolves to a static, ratcheted style.
39
+ const accentColorStyles = {
40
+ LIME: "_syaz1tco",
41
+ RED: "_syaz9lu1",
42
+ ORANGE: "_syazp1lv",
43
+ YELLOW: "_syazfb2s",
44
+ GREEN: "_syazh55r",
45
+ TEAL: "_syaz17qg",
46
+ BLUE: "_syaz16jw",
47
+ PURPLE: "_syazqmo9",
48
+ MAGENTA: "_syaz1s8m",
49
+ GRAY: "_syaz1sqi",
50
+ DEFAULT: "_syazazsu"
51
+ };
52
+ const isAccentColor = color => Boolean(color && color in accentColorStyles);
53
+ /**
54
+ * Renders a skill as a tag/chip label in the quick-insert typeahead list, instead of plain text,
55
+ * mirroring the "/" + slug layout of the inserted skill chip (SkillTag). Never shows a hovercard
56
+ * — this is a lightweight label for the list row, not the inserted chip.
57
+ */
58
+ export const SkillTagLabel = ({
59
+ color,
60
+ slug
61
+ }) => {
62
+ const accentColor = isAccentColor(color) ? color : 'DEFAULT';
63
+ return /*#__PURE__*/React.createElement(Box, {
64
+ as: "span",
65
+ xcss: styles.tag
66
+ }, /*#__PURE__*/React.createElement(Box, {
67
+ as: "span",
68
+ xcss: cx(styles.slash, accentColorStyles[accentColor])
69
+ }, "/"), /*#__PURE__*/React.createElement(Text, {
70
+ as: "span"
71
+ }, slug));
72
+ };
@@ -17,6 +17,8 @@ import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
17
17
  import ButtonItem from '@atlaskit/menu/button-item';
18
18
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
19
19
  import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
20
+ import { parseSkillTagTitle, SkillTagLabel } from './SkillTagLabel';
21
+
20
22
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
21
23
  export const itemIcon = css({
22
24
  width: "var(--ds-space-500, 40px)",
@@ -181,6 +183,7 @@ export const TypeAheadListItem = /*#__PURE__*/React.memo(({
181
183
  firstOnlineSupportedIndex,
182
184
  lastInputMethodRef
183
185
  }) => {
186
+ var _skillTag$name;
184
187
  const isSafari = getBrowserInfo().safari;
185
188
  const {
186
189
  connectivityMode
@@ -219,6 +222,7 @@ export const TypeAheadListItem = /*#__PURE__*/React.memo(({
219
222
  title,
220
223
  render: customRenderItem
221
224
  } = item;
225
+ const skillTag = useMemo(() => isExperimentEnabled('display_skill_lozenge_in_editor') ? parseSkillTagTitle(title) : undefined, [title]);
222
226
  const elementIcon = useMemo(() => {
223
227
  return jsx("div", {
224
228
  css: [itemIcon, moreElementsInQuickInsertViewEnabled && itemIconSizeUpdated]
@@ -277,7 +281,7 @@ export const TypeAheadListItem = /*#__PURE__*/React.memo(({
277
281
  iconBefore: elementIcon,
278
282
  isSelected: isSelected,
279
283
  "aria-selected": isSelected,
280
- "aria-label": title,
284
+ "aria-label": (_skillTag$name = skillTag === null || skillTag === void 0 ? void 0 : skillTag.name) !== null && _skillTag$name !== void 0 ? _skillTag$name : title,
281
285
  "aria-describedby": descriptionText || shortcutText ? descriptionId : undefined,
282
286
  "aria-setsize": itemsLength,
283
287
  "aria-posinset": itemIndex + 1,
@@ -296,7 +300,10 @@ export const TypeAheadListItem = /*#__PURE__*/React.memo(({
296
300
  css: itemBody
297
301
  }, jsx("div", {
298
302
  css: [itemTitle, moreElementsInQuickInsertViewEnabled && itemTitleOverride, itemIsDisabled && disabledStyle, item.lozenge && titleWithLozengeStyle]
299
- }, item.title, item.lozenge && jsx("span", {
303
+ }, skillTag ? jsx(SkillTagLabel, {
304
+ color: skillTag.color,
305
+ slug: skillTag.slug
306
+ }) : item.title, item.lozenge && jsx("span", {
300
307
  css: lozengeWrapperStyle
301
308
  }, item.lozenge)), jsx("div", {
302
309
  css: itemAfter
@@ -1,7 +1,8 @@
1
- ._2rko12b0{border-radius:var(--ds-radius-small,4px)}
2
- ._1rjc1b66{padding-block:var(--ds-space-050,4px)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
1
+ ._2rko1mok{border-radius:var(--ds-radius-large,8px)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
3
2
  ._18m915vq{overflow-y:hidden}
4
3
  ._1bsbnklw{width:20pc}
4
+ ._1q51u2gc{padding-block-start:var(--ds-space-100,8px)}
5
5
  ._1reo15vq{overflow-x:hidden}
6
+ ._85i512x7{padding-block-end:var(--ds-space-075,6px)}
6
7
  ._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
7
8
  ._vchhusvi{box-sizing:border-box}
@@ -1,9 +1,10 @@
1
1
  /* RegisteredTypeAheadMenu.tsx generated by @compiled/babel-plugin v3.0.2 */
2
2
  import "./RegisteredTypeAheadMenu.compiled.css";
3
3
  import { ax, ix } from "@compiled/react/runtime";
4
- import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
4
+ import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
5
5
  import { useIntl } from 'react-intl';
6
6
  import { buildQuickInsertMenuModel, getMatchingQuickInsertComponents, selectQuickInsertCategoryItems } from '@atlaskit/editor-common/quick-insert/registered-menu-model';
7
+ import { useMenuPopupSizing } from '@atlaskit/editor-common/quick-insert/use-menu-popup-sizing';
7
8
  import { isSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-is-section-overflow-item-key';
8
9
  import { TYPE_AHEAD_SURFACE_CONTEXT } from '@atlaskit/editor-common/type-ahead-surface-context';
9
10
  import { Popup } from '@atlaskit/editor-common/ui';
@@ -17,12 +18,14 @@ import { getTypeAheadItemId } from './getTypeAheadItemId';
17
18
  import { TypeAheadMenuRenderer } from './TypeAheadMenuRenderer';
18
19
  import { TypeAheadProvider } from './TypeAheadProvider';
19
20
  const styles = {
20
- menu: "_2rko12b0 _1reo15vq _18m915vq _1rjc1b66 _bfhk1bhr _vchhusvi _16qs130s _1bsbnklw"
21
+ menu: "_2rko1mok _1reo15vq _18m915vq _bfhk1bhr _vchhusvi _16qs130s _1q51u2gc _85i512x7 _1bsbnklw"
21
22
  };
22
23
  const DEFAULT_MENU_MAX_HEIGHT = 480;
23
- const MENU_VERTICAL_PADDING = 8;
24
+ const MENU_VERTICAL_PADDING = 14;
24
25
  const MENU_WIDTH = 320;
25
26
  const POPUP_OFFSET = [0, 8];
27
+ const EMPTY_COMPONENTS = [];
28
+ const subscribeToNothing = () => () => {};
26
29
  export const RegisteredTypeAheadMenu = ({
27
30
  anchorElement,
28
31
  api,
@@ -41,6 +44,14 @@ export const RegisteredTypeAheadMenu = ({
41
44
  surface,
42
45
  triggerHandler
43
46
  }) => {
47
+ var _api$uiControlRegistr2, _api$uiControlRegistr3;
48
+ const menuHeight = useMenuPopupSizing({
49
+ target: anchorElement,
50
+ boundariesElement: popupsBoundariesElement,
51
+ scrollableElement: popupsScrollableElement,
52
+ maxHeight,
53
+ offset: POPUP_OFFSET[1]
54
+ });
44
55
  const {
45
56
  formatMessage
46
57
  } = useIntl();
@@ -52,10 +63,12 @@ export const RegisteredTypeAheadMenu = ({
52
63
  }));
53
64
  const surfaceContext = useMemo(() => createSurfaceContext(TYPE_AHEAD_SURFACE_CONTEXT, typeAheadSurfaceContext), [typeAheadSurfaceContext]);
54
65
  const [selectedItemIndex, setSelectedItemIndex] = useState(0);
55
- const components = useMemo(() => {
56
- var _api$uiControlRegistr, _api$uiControlRegistr2;
57
- return (_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(surface.root.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
66
+ const getComponents = useCallback(() => {
67
+ var _api$uiControlRegistr;
68
+ const components = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 ? void 0 : _api$uiControlRegistr.actions.getComponents(surface.root.key);
69
+ return components !== null && components !== void 0 && components.length ? components : EMPTY_COMPONENTS;
58
70
  }, [api, surface.root.key]);
71
+ const components = useSyncExternalStore((_api$uiControlRegistr2 = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr3 = api.uiControlRegistry) === null || _api$uiControlRegistr3 === void 0 ? void 0 : _api$uiControlRegistr3.actions.subscribe) !== null && _api$uiControlRegistr2 !== void 0 ? _api$uiControlRegistr2 : subscribeToNothing, getComponents, getComponents);
59
72
  const isSlashCommandEnabled = isExperimentEnabled('platform_editor_slash_command');
60
73
  const hasSectionOverflowItems = useMemo(() => components.some(({
61
74
  key
@@ -135,7 +148,7 @@ export const RegisteredTypeAheadMenu = ({
135
148
  }), /*#__PURE__*/React.createElement(Popup, {
136
149
  ariaLabel: null,
137
150
  boundariesElement: popupsBoundariesElement,
138
- fitHeight: maxHeight,
151
+ fitHeight: menuHeight,
139
152
  fitWidth: MENU_WIDTH,
140
153
  mountTo: popupsMountPoint,
141
154
  offset: POPUP_OFFSET,
@@ -154,7 +167,7 @@ export const RegisteredTypeAheadMenu = ({
154
167
  Item: surface.Item,
155
168
  listLabel: surface.listLabel,
156
169
  listId: listId,
157
- maxHeight: Math.max(0, maxHeight - MENU_VERTICAL_PADDING),
170
+ maxHeight: Math.max(0, menuHeight - MENU_VERTICAL_PADDING),
158
171
  model: menuModel,
159
172
  onItemHover: setSelectedItemIndex,
160
173
  selectedItemIndex: selectedItemIndex
@@ -2,6 +2,7 @@ import React, { useCallback, useLayoutEffect, useMemo, useRef } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import { CellMeasurerCache } from 'react-virtualized/dist/commonjs/CellMeasurer';
4
4
  import { List } from 'react-virtualized/dist/commonjs/List';
5
+ import { useMenuListHeight } from '@atlaskit/editor-common/quick-insert/use-menu-list-height';
5
6
  import { typeAheadListMessages } from '@atlaskit/editor-common/type-ahead';
6
7
  import { Box, Text } from '@atlaskit/primitives/compiled';
7
8
  import { createTypeAheadRowRenderer } from './createTypeAheadRowRenderer';
@@ -10,7 +11,8 @@ import { PassThrough } from './PassThrough';
10
11
  import { TypeAheadMenuFooter } from './TypeAheadMenuFooter';
11
12
  const LIST_WIDTH = 320;
12
13
  const ESTIMATED_ROW_HEIGHT = 56;
13
- const MENU_FOOTER_HEIGHT = 48;
14
+ // 40px item + 8px block padding + 1px separator.
15
+ const MENU_FOOTER_HEIGHT = 49;
14
16
  export const TypeAheadMenuRenderer = ({
15
17
  Item,
16
18
  listLabel,
@@ -53,6 +55,10 @@ export const TypeAheadMenuRenderer = ({
53
55
  key,
54
56
  type
55
57
  }) => `${type}:${key}`).join('\0'), [rows]);
58
+ const {
59
+ height: measuredHeight,
60
+ updateHeight
61
+ } = useMenuListHeight(cache, rows.length, rowKeySignature);
56
62
  useLayoutEffect(() => {
57
63
  var _listRef$current, _listRef$current2;
58
64
  cache.clearAll();
@@ -67,6 +73,7 @@ export const TypeAheadMenuRenderer = ({
67
73
  }, [selectedRowIndex]);
68
74
  const renderRow = createTypeAheadRowRenderer({
69
75
  cache,
76
+ onMeasured: updateHeight,
70
77
  itemIndexByRowIndex,
71
78
  Item,
72
79
  listId,
@@ -88,7 +95,8 @@ export const TypeAheadMenuRenderer = ({
88
95
  role: hasListboxContent ? 'listbox' : undefined
89
96
  }, rows.length > 0 ? /*#__PURE__*/React.createElement(List, {
90
97
  containerRole: "presentation",
91
- height: Math.min(rows.length * ESTIMATED_ROW_HEIGHT, listMaxHeight),
98
+ height: Math.min(measuredHeight, listMaxHeight),
99
+ onRowsRendered: updateHeight,
92
100
  overscanRowCount: 3,
93
101
  ref: listRef,
94
102
  role: "presentation",
@@ -6,6 +6,7 @@ import { TypeAheadSectionRow } from './TypeAheadSectionRow';
6
6
  const noOp = () => {};
7
7
  export const createTypeAheadRowRenderer = ({
8
8
  cache,
9
+ onMeasured,
9
10
  itemIndexByRowIndex,
10
11
  Item,
11
12
  listId,
@@ -38,6 +39,7 @@ export const createTypeAheadRowRenderer = ({
38
39
  isScrolling: isScrolling,
39
40
  isVisible: isVisible,
40
41
  measure: measure,
42
+ onMeasured: onMeasured,
41
43
  onMouseMove: noOp,
42
44
  style: style
43
45
  }, registration.type === 'menu-section' ? /*#__PURE__*/React.createElement(TypeAheadSectionRow, {
@@ -16,6 +16,7 @@ import React, { useEffect, useRef, forwardRef } from 'react';
16
16
  export var ListRow = /*#__PURE__*/forwardRef(function (_ref, ref) {
17
17
  var children = _ref.children,
18
18
  measure = _ref.measure,
19
+ onMeasured = _ref.onMeasured,
19
20
  index = _ref.index,
20
21
  style = _ref.style,
21
22
  isVisible = _ref.isVisible,
@@ -28,13 +29,14 @@ export var ListRow = /*#__PURE__*/forwardRef(function (_ref, ref) {
28
29
  return;
29
30
  }
30
31
  var observer = new ResizeObserver(function () {
31
- return measure();
32
+ measure();
33
+ onMeasured === null || onMeasured === void 0 || onMeasured();
32
34
  });
33
35
  observer.observe(childElementRef.current);
34
36
  return function () {
35
37
  return observer.disconnect();
36
38
  };
37
- }, [isScrolling, isVisible, measure]);
39
+ }, [isScrolling, isVisible, measure, onMeasured]);
38
40
  return (
39
41
  /*#__PURE__*/
40
42
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
@@ -0,0 +1,19 @@
1
+ ._2rkolb4i{border-radius:var(--ds-radius-xsmall,2px)}._16d9qvcn{-webkit-box-decoration-break:clone;box-decoration-break:clone}
2
+ ._18u01b66{margin-left:var(--ds-space-050,4px)}
3
+ ._19bv1b66{padding-left:var(--ds-space-050,4px)}
4
+ ._1e0c1nu9{display:inline}
5
+ ._2hwx1b66{margin-right:var(--ds-space-050,4px)}
6
+ ._bfhki8nm{background-color:var(--ds-background-neutral,#0515240f)}
7
+ ._syaz16jw{color:var(--ds-text-accent-blue,#1558bc)}
8
+ ._syaz17qg{color:var(--ds-text-accent-teal,#206a83)}
9
+ ._syaz1s8m{color:var(--ds-text-accent-magenta,#943d73)}
10
+ ._syaz1sqi{color:var(--ds-text-accent-gray,#505258)}
11
+ ._syaz1tco{color:var(--ds-text-accent-lime,#4c6b1f)}
12
+ ._syaz9lu1{color:var(--ds-text-accent-red,#ae2e24)}
13
+ ._syazazsu{color:var(--ds-text-subtle,#505258)}
14
+ ._syazfb2s{color:var(--ds-text-accent-yellow,#7f5f01)}
15
+ ._syazh55r{color:var(--ds-text-accent-green,#216e4e)}
16
+ ._syazp1lv{color:var(--ds-text-accent-orange,#9e4c00)}
17
+ ._syazqmo9{color:var(--ds-text-accent-purple,#803fa5)}
18
+ ._u5f31b66{padding-right:var(--ds-space-050,4px)}
19
+ ._vchhusvi{box-sizing:border-box}
@@ -0,0 +1,79 @@
1
+ /* SkillTagLabel.tsx generated by @compiled/babel-plugin v3.0.2 */
2
+ import _toArray from "@babel/runtime/helpers/toArray";
3
+ import "./SkillTagLabel.compiled.css";
4
+ import * as React from 'react';
5
+ import { ax, ix } from "@compiled/react/runtime";
6
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
7
+ import { cx } from '@atlaskit/css';
8
+ import { Box } from '@atlaskit/primitives/compiled/box';
9
+ import { Text } from '@atlaskit/primitives/compiled/text';
10
+ var SKILL_TITLE_PREFIX = 'skill::';
11
+ /**
12
+ * Parses a quick-insert item title of the form `skill::{COLOR}::{SLUG}::{NAME}`, produced by the
13
+ * Rovo skills quick-insert manifest when `display_skill_lozenge_in_editor` is enabled. Returns
14
+ * undefined for any title that isn't in this format.
15
+ */
16
+ export var parseSkillTagTitle = function parseSkillTagTitle(title) {
17
+ if (!title.startsWith(SKILL_TITLE_PREFIX)) {
18
+ return undefined;
19
+ }
20
+ var _title$split = title.split('::'),
21
+ _title$split2 = _toArray(_title$split),
22
+ color = _title$split2[1],
23
+ slug = _title$split2[2],
24
+ nameParts = _arrayLikeToArray(_title$split2).slice(3);
25
+ var name = nameParts.join('::');
26
+ if (!slug || !name) {
27
+ return undefined;
28
+ }
29
+ return {
30
+ color: color || undefined,
31
+ slug: slug,
32
+ name: name
33
+ };
34
+ };
35
+ var styles = {
36
+ tag: "_2rkolb4i _1e0c1nu9 _16d9qvcn _vchhusvi _18u01b66 _19bv1b66 _u5f31b66 _bfhki8nm",
37
+ slash: "_1e0c1nu9 _2hwx1b66"
38
+ };
39
+
40
+ // Slash accent colors for a Rovo skill, mirroring the enum used by the inserted skill chip
41
+ // (@atlassian/rovo-platform-ui-components/skills/skill-colors). Duplicated here — rather than
42
+ // imported — so this shared, product-agnostic editor package doesn't take on a dependency on an
43
+ // ai-mate/Rovo UI package. Modelled as a finite cssMap (rather than a runtime style override) so
44
+ // each color resolves to a static, ratcheted style.
45
+ var accentColorStyles = {
46
+ LIME: "_syaz1tco",
47
+ RED: "_syaz9lu1",
48
+ ORANGE: "_syazp1lv",
49
+ YELLOW: "_syazfb2s",
50
+ GREEN: "_syazh55r",
51
+ TEAL: "_syaz17qg",
52
+ BLUE: "_syaz16jw",
53
+ PURPLE: "_syazqmo9",
54
+ MAGENTA: "_syaz1s8m",
55
+ GRAY: "_syaz1sqi",
56
+ DEFAULT: "_syazazsu"
57
+ };
58
+ var isAccentColor = function isAccentColor(color) {
59
+ return Boolean(color && color in accentColorStyles);
60
+ };
61
+ /**
62
+ * Renders a skill as a tag/chip label in the quick-insert typeahead list, instead of plain text,
63
+ * mirroring the "/" + slug layout of the inserted skill chip (SkillTag). Never shows a hovercard
64
+ * — this is a lightweight label for the list row, not the inserted chip.
65
+ */
66
+ export var SkillTagLabel = function SkillTagLabel(_ref) {
67
+ var color = _ref.color,
68
+ slug = _ref.slug;
69
+ var accentColor = isAccentColor(color) ? color : 'DEFAULT';
70
+ return /*#__PURE__*/React.createElement(Box, {
71
+ as: "span",
72
+ xcss: styles.tag
73
+ }, /*#__PURE__*/React.createElement(Box, {
74
+ as: "span",
75
+ xcss: cx(styles.slash, accentColorStyles[accentColor])
76
+ }, "/"), /*#__PURE__*/React.createElement(Text, {
77
+ as: "span"
78
+ }, slug));
79
+ };
@@ -19,6 +19,8 @@ import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
19
19
  import ButtonItem from '@atlaskit/menu/button-item';
20
20
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
21
21
  import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
22
+ import { parseSkillTagTitle, SkillTagLabel } from './SkillTagLabel';
23
+
22
24
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
23
25
  export var itemIcon = css({
24
26
  width: "var(--ds-space-500, 40px)",
@@ -153,6 +155,7 @@ var CustomItemComponentWrapper = /*#__PURE__*/React.memo(function (props) {
153
155
  })));
154
156
  });
155
157
  export var TypeAheadListItem = /*#__PURE__*/React.memo(function (_ref) {
158
+ var _skillTag$name;
156
159
  var item = _ref.item,
157
160
  itemsLength = _ref.itemsLength,
158
161
  selectedIndex = _ref.selectedIndex,
@@ -198,6 +201,9 @@ export var TypeAheadListItem = /*#__PURE__*/React.memo(function (_ref) {
198
201
  var icon = item.icon,
199
202
  title = item.title,
200
203
  customRenderItem = item.render;
204
+ var skillTag = useMemo(function () {
205
+ return isExperimentEnabled('display_skill_lozenge_in_editor') ? parseSkillTagTitle(title) : undefined;
206
+ }, [title]);
201
207
  var elementIcon = useMemo(function () {
202
208
  return jsx("div", {
203
209
  css: [itemIcon, moreElementsInQuickInsertViewEnabled && itemIconSizeUpdated]
@@ -256,7 +262,7 @@ export var TypeAheadListItem = /*#__PURE__*/React.memo(function (_ref) {
256
262
  iconBefore: elementIcon,
257
263
  isSelected: isSelected,
258
264
  "aria-selected": isSelected,
259
- "aria-label": title,
265
+ "aria-label": (_skillTag$name = skillTag === null || skillTag === void 0 ? void 0 : skillTag.name) !== null && _skillTag$name !== void 0 ? _skillTag$name : title,
260
266
  "aria-describedby": descriptionText || shortcutText ? descriptionId : undefined,
261
267
  "aria-setsize": itemsLength,
262
268
  "aria-posinset": itemIndex + 1,
@@ -275,7 +281,10 @@ export var TypeAheadListItem = /*#__PURE__*/React.memo(function (_ref) {
275
281
  css: itemBody
276
282
  }, jsx("div", {
277
283
  css: [itemTitle, moreElementsInQuickInsertViewEnabled && itemTitleOverride, itemIsDisabled && disabledStyle, item.lozenge && titleWithLozengeStyle]
278
- }, item.title, item.lozenge && jsx("span", {
284
+ }, skillTag ? jsx(SkillTagLabel, {
285
+ color: skillTag.color,
286
+ slug: skillTag.slug
287
+ }) : item.title, item.lozenge && jsx("span", {
279
288
  css: lozengeWrapperStyle
280
289
  }, item.lozenge)), jsx("div", {
281
290
  css: itemAfter
@@ -1,7 +1,8 @@
1
- ._2rko12b0{border-radius:var(--ds-radius-small,4px)}
2
- ._1rjc1b66{padding-block:var(--ds-space-050,4px)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
1
+ ._2rko1mok{border-radius:var(--ds-radius-large,8px)}._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
3
2
  ._18m915vq{overflow-y:hidden}
4
3
  ._1bsbnklw{width:20pc}
4
+ ._1q51u2gc{padding-block-start:var(--ds-space-100,8px)}
5
5
  ._1reo15vq{overflow-x:hidden}
6
+ ._85i512x7{padding-block-end:var(--ds-space-075,6px)}
6
7
  ._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
7
8
  ._vchhusvi{box-sizing:border-box}
@@ -3,9 +3,10 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  import "./RegisteredTypeAheadMenu.compiled.css";
5
5
  import { ax, ix } from "@compiled/react/runtime";
6
- import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
6
+ import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
7
7
  import { useIntl } from 'react-intl';
8
8
  import { buildQuickInsertMenuModel, getMatchingQuickInsertComponents, selectQuickInsertCategoryItems } from '@atlaskit/editor-common/quick-insert/registered-menu-model';
9
+ import { useMenuPopupSizing } from '@atlaskit/editor-common/quick-insert/use-menu-popup-sizing';
9
10
  import { isSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-is-section-overflow-item-key';
10
11
  import { TYPE_AHEAD_SURFACE_CONTEXT } from '@atlaskit/editor-common/type-ahead-surface-context';
11
12
  import { Popup } from '@atlaskit/editor-common/ui';
@@ -19,13 +20,18 @@ import { getTypeAheadItemId } from './getTypeAheadItemId';
19
20
  import { TypeAheadMenuRenderer } from './TypeAheadMenuRenderer';
20
21
  import { TypeAheadProvider } from './TypeAheadProvider';
21
22
  var styles = {
22
- menu: "_2rko12b0 _1reo15vq _18m915vq _1rjc1b66 _bfhk1bhr _vchhusvi _16qs130s _1bsbnklw"
23
+ menu: "_2rko1mok _1reo15vq _18m915vq _bfhk1bhr _vchhusvi _16qs130s _1q51u2gc _85i512x7 _1bsbnklw"
23
24
  };
24
25
  var DEFAULT_MENU_MAX_HEIGHT = 480;
25
- var MENU_VERTICAL_PADDING = 8;
26
+ var MENU_VERTICAL_PADDING = 14;
26
27
  var MENU_WIDTH = 320;
27
28
  var POPUP_OFFSET = [0, 8];
29
+ var EMPTY_COMPONENTS = [];
30
+ var subscribeToNothing = function subscribeToNothing() {
31
+ return function () {};
32
+ };
28
33
  export var RegisteredTypeAheadMenu = function RegisteredTypeAheadMenu(_ref) {
34
+ var _api$uiControlRegistr2, _api$uiControlRegistr3;
29
35
  var anchorElement = _ref.anchorElement,
30
36
  api = _ref.api,
31
37
  cancel = _ref.cancel,
@@ -43,6 +49,13 @@ export var RegisteredTypeAheadMenu = function RegisteredTypeAheadMenu(_ref) {
43
49
  setQuery = _ref.setQuery,
44
50
  surface = _ref.surface,
45
51
  triggerHandler = _ref.triggerHandler;
52
+ var menuHeight = useMenuPopupSizing({
53
+ target: anchorElement,
54
+ boundariesElement: popupsBoundariesElement,
55
+ scrollableElement: popupsScrollableElement,
56
+ maxHeight: maxHeight,
57
+ offset: POPUP_OFFSET[1]
58
+ });
46
59
  var _useIntl = useIntl(),
47
60
  formatMessage = _useIntl.formatMessage;
48
61
  var generatedId = useId();
@@ -62,10 +75,12 @@ export var RegisteredTypeAheadMenu = function RegisteredTypeAheadMenu(_ref) {
62
75
  _useState4 = _slicedToArray(_useState3, 2),
63
76
  selectedItemIndex = _useState4[0],
64
77
  setSelectedItemIndex = _useState4[1];
65
- var components = useMemo(function () {
66
- var _api$uiControlRegistr, _api$uiControlRegistr2;
67
- return (_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(surface.root.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
78
+ var getComponents = useCallback(function () {
79
+ var _api$uiControlRegistr;
80
+ var components = api === null || api === void 0 || (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 ? void 0 : _api$uiControlRegistr.actions.getComponents(surface.root.key);
81
+ return components !== null && components !== void 0 && components.length ? components : EMPTY_COMPONENTS;
68
82
  }, [api, surface.root.key]);
83
+ var components = useSyncExternalStore((_api$uiControlRegistr2 = api === null || api === void 0 || (_api$uiControlRegistr3 = api.uiControlRegistry) === null || _api$uiControlRegistr3 === void 0 ? void 0 : _api$uiControlRegistr3.actions.subscribe) !== null && _api$uiControlRegistr2 !== void 0 ? _api$uiControlRegistr2 : subscribeToNothing, getComponents, getComponents);
69
84
  var isSlashCommandEnabled = isExperimentEnabled('platform_editor_slash_command');
70
85
  var hasSectionOverflowItems = useMemo(function () {
71
86
  return components.some(function (_ref2) {
@@ -156,7 +171,7 @@ export var RegisteredTypeAheadMenu = function RegisteredTypeAheadMenu(_ref) {
156
171
  }), /*#__PURE__*/React.createElement(Popup, {
157
172
  ariaLabel: null,
158
173
  boundariesElement: popupsBoundariesElement,
159
- fitHeight: maxHeight,
174
+ fitHeight: menuHeight,
160
175
  fitWidth: MENU_WIDTH,
161
176
  mountTo: popupsMountPoint,
162
177
  offset: POPUP_OFFSET,
@@ -175,7 +190,7 @@ export var RegisteredTypeAheadMenu = function RegisteredTypeAheadMenu(_ref) {
175
190
  Item: surface.Item,
176
191
  listLabel: surface.listLabel,
177
192
  listId: listId,
178
- maxHeight: Math.max(0, maxHeight - MENU_VERTICAL_PADDING),
193
+ maxHeight: Math.max(0, menuHeight - MENU_VERTICAL_PADDING),
179
194
  model: menuModel,
180
195
  onItemHover: setSelectedItemIndex,
181
196
  selectedItemIndex: selectedItemIndex
@@ -7,6 +7,7 @@ import React, { useCallback, useLayoutEffect, useMemo, useRef } from 'react';
7
7
  import { useIntl } from 'react-intl';
8
8
  import { CellMeasurerCache } from 'react-virtualized/dist/commonjs/CellMeasurer';
9
9
  import { List } from 'react-virtualized/dist/commonjs/List';
10
+ import { useMenuListHeight } from '@atlaskit/editor-common/quick-insert/use-menu-list-height';
10
11
  import { typeAheadListMessages } from '@atlaskit/editor-common/type-ahead';
11
12
  import { Box, Text } from '@atlaskit/primitives/compiled';
12
13
  import { createTypeAheadRowRenderer } from './createTypeAheadRowRenderer';
@@ -15,7 +16,8 @@ import { PassThrough } from './PassThrough';
15
16
  import { TypeAheadMenuFooter } from './TypeAheadMenuFooter';
16
17
  var LIST_WIDTH = 320;
17
18
  var ESTIMATED_ROW_HEIGHT = 56;
18
- var MENU_FOOTER_HEIGHT = 48;
19
+ // 40px item + 8px block padding + 1px separator.
20
+ var MENU_FOOTER_HEIGHT = 49;
19
21
  export var TypeAheadMenuRenderer = function TypeAheadMenuRenderer(_ref) {
20
22
  var _model$root$component;
21
23
  var Item = _ref.Item,
@@ -73,6 +75,9 @@ export var TypeAheadMenuRenderer = function TypeAheadMenuRenderer(_ref) {
73
75
  return "".concat(type, ":").concat(key);
74
76
  }).join('\0');
75
77
  }, [rows]);
78
+ var _useMenuListHeight = useMenuListHeight(cache, rows.length, rowKeySignature),
79
+ measuredHeight = _useMenuListHeight.height,
80
+ updateHeight = _useMenuListHeight.updateHeight;
76
81
  useLayoutEffect(function () {
77
82
  var _listRef$current, _listRef$current2;
78
83
  cache.clearAll();
@@ -87,6 +92,7 @@ export var TypeAheadMenuRenderer = function TypeAheadMenuRenderer(_ref) {
87
92
  }, [selectedRowIndex]);
88
93
  var renderRow = createTypeAheadRowRenderer({
89
94
  cache: cache,
95
+ onMeasured: updateHeight,
90
96
  itemIndexByRowIndex: itemIndexByRowIndex,
91
97
  Item: Item,
92
98
  listId: listId,
@@ -110,7 +116,8 @@ export var TypeAheadMenuRenderer = function TypeAheadMenuRenderer(_ref) {
110
116
  role: hasListboxContent ? 'listbox' : undefined
111
117
  }, rows.length > 0 ? /*#__PURE__*/React.createElement(List, {
112
118
  containerRole: "presentation",
113
- height: Math.min(rows.length * ESTIMATED_ROW_HEIGHT, listMaxHeight),
119
+ height: Math.min(measuredHeight, listMaxHeight),
120
+ onRowsRendered: updateHeight,
114
121
  overscanRowCount: 3,
115
122
  ref: listRef,
116
123
  role: "presentation",
@@ -6,6 +6,7 @@ import { TypeAheadSectionRow } from './TypeAheadSectionRow';
6
6
  var noOp = function noOp() {};
7
7
  export var createTypeAheadRowRenderer = function createTypeAheadRowRenderer(_ref) {
8
8
  var cache = _ref.cache,
9
+ onMeasured = _ref.onMeasured,
9
10
  itemIndexByRowIndex = _ref.itemIndexByRowIndex,
10
11
  Item = _ref.Item,
11
12
  listId = _ref.listId,
@@ -37,6 +38,7 @@ export var createTypeAheadRowRenderer = function createTypeAheadRowRenderer(_ref
37
38
  isScrolling: isScrolling,
38
39
  isVisible: isVisible,
39
40
  measure: measure,
41
+ onMeasured: onMeasured,
40
42
  onMouseMove: noOp,
41
43
  style: style
42
44
  }, registration.type === 'menu-section' ? /*#__PURE__*/React.createElement(TypeAheadSectionRow, {
@@ -17,5 +17,6 @@ import type { ListRowProps } from 'react-virtualized';
17
17
  export declare const ListRow: React.ForwardRefExoticComponent<{
18
18
  children: ReactNode;
19
19
  measure: () => void;
20
+ onMeasured?: () => void;
20
21
  onMouseMove: MouseEventHandler<HTMLDivElement>;
21
22
  } & Pick<ListRowProps, 'index' | 'isScrolling' | 'isVisible' | 'style'> & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,21 @@
1
+ export type ParsedSkillTag = {
2
+ color?: string;
3
+ name: string;
4
+ slug: string;
5
+ };
6
+ /**
7
+ * Parses a quick-insert item title of the form `skill::{COLOR}::{SLUG}::{NAME}`, produced by the
8
+ * Rovo skills quick-insert manifest when `display_skill_lozenge_in_editor` is enabled. Returns
9
+ * undefined for any title that isn't in this format.
10
+ */
11
+ export declare const parseSkillTagTitle: (title: string) => ParsedSkillTag | undefined;
12
+ export type SkillTagLabelProps = {
13
+ color?: string;
14
+ slug: string;
15
+ };
16
+ /**
17
+ * Renders a skill as a tag/chip label in the quick-insert typeahead list, instead of plain text,
18
+ * mirroring the "/" + slug layout of the inserted skill chip (SkillTag). Never shows a hovercard
19
+ * — this is a lightweight label for the list row, not the inserted chip.
20
+ */
21
+ export declare const SkillTagLabel: ({ color, slug }: SkillTagLabelProps) => JSX.Element;
@@ -2,12 +2,13 @@ import type { CellMeasurerCache } from 'react-virtualized/dist/commonjs/CellMeas
2
2
  import type { ListRowRenderer } from 'react-virtualized/dist/commonjs/List';
3
3
  import type { RegisterMenuItem, RegisterMenuSection } from '@atlaskit/editor-ui-control-model/types';
4
4
  import type { TypeAheadItemComponent } from './typeAheadMenuTypes';
5
- export declare const createTypeAheadRowRenderer: ({ cache, itemIndexByRowIndex, Item, listId, onItemHover, rows, selectedItemIndex, }: {
5
+ export declare const createTypeAheadRowRenderer: ({ cache, onMeasured, itemIndexByRowIndex, Item, listId, onItemHover, rows, selectedItemIndex, }: {
6
6
  cache: CellMeasurerCache;
7
7
  Item: TypeAheadItemComponent;
8
8
  itemIndexByRowIndex: Map<number, number>;
9
9
  listId: string;
10
10
  onItemHover: (itemIndex: number) => void;
11
+ onMeasured: () => void;
11
12
  rows: Array<RegisterMenuItem | RegisterMenuSection>;
12
13
  selectedItemIndex: number;
13
14
  }) => ListRowRenderer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-type-ahead",
3
- "version": "22.0.3",
3
+ "version": "22.1.1",
4
4
  "description": "Type-ahead plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -42,7 +42,7 @@
42
42
  "@atlaskit/primitives": "^22.5.0",
43
43
  "@atlaskit/prosemirror-history": "^1.2.0",
44
44
  "@atlaskit/prosemirror-input-rules": "^4.1.0",
45
- "@atlaskit/tmp-editor-statsig": "^208.0.0",
45
+ "@atlaskit/tmp-editor-statsig": "^209.0.0",
46
46
  "@atlaskit/tokens": "^20.0.0",
47
47
  "@atlaskit/visually-hidden": "^4.4.0",
48
48
  "@babel/runtime": "^7.0.0",
@@ -54,7 +54,7 @@
54
54
  "w3c-keyname": "^2.1.8"
55
55
  },
56
56
  "peerDependencies": {
57
- "@atlaskit/editor-common": "^125.2.0",
57
+ "@atlaskit/editor-common": "^125.4.0",
58
58
  "react": "^18.2.0 || ^19.2.0",
59
59
  "react-dom": "^18.2.0 || ^19.2.0",
60
60
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"