@atlaskit/editor-plugin-quick-insert 30.0.2 → 30.0.4

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 (36) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cjs/quickInsertPlugin.js +6 -2
  3. package/dist/cjs/ui/getQuickInsertComponents.js +8 -53
  4. package/dist/cjs/ui/getRecommendedComponents.js +19 -38
  5. package/dist/cjs/ui/registered-menu/QuickInsertMenuRoot.js +10 -5
  6. package/dist/cjs/ui/registered-menu/RegisteredQuickInsertMenuItem.js +5 -3
  7. package/dist/cjs/ui/registered-menu/ToolbarQuickInsertMenu.js +3 -1
  8. package/dist/cjs/ui/registered-menu/TypeAheadQuickInsertMenu.js +2 -0
  9. package/dist/cjs/ui/registered-menu/get-quick-insert-menu-model.js +175 -88
  10. package/dist/es2019/quickInsertPlugin.js +6 -2
  11. package/dist/es2019/ui/getQuickInsertComponents.js +6 -43
  12. package/dist/es2019/ui/getRecommendedComponents.js +17 -37
  13. package/dist/es2019/ui/registered-menu/QuickInsertMenuRoot.js +9 -4
  14. package/dist/es2019/ui/registered-menu/RegisteredQuickInsertMenuItem.js +5 -3
  15. package/dist/es2019/ui/registered-menu/ToolbarQuickInsertMenu.js +3 -1
  16. package/dist/es2019/ui/registered-menu/TypeAheadQuickInsertMenu.js +2 -0
  17. package/dist/es2019/ui/registered-menu/get-quick-insert-menu-model.js +128 -55
  18. package/dist/esm/quickInsertPlugin.js +6 -2
  19. package/dist/esm/ui/getQuickInsertComponents.js +8 -53
  20. package/dist/esm/ui/getRecommendedComponents.js +18 -37
  21. package/dist/esm/ui/registered-menu/QuickInsertMenuRoot.js +10 -5
  22. package/dist/esm/ui/registered-menu/RegisteredQuickInsertMenuItem.js +5 -3
  23. package/dist/esm/ui/registered-menu/ToolbarQuickInsertMenu.js +3 -1
  24. package/dist/esm/ui/registered-menu/TypeAheadQuickInsertMenu.js +2 -0
  25. package/dist/esm/ui/registered-menu/get-quick-insert-menu-model.js +176 -89
  26. package/dist/types/ui/getQuickInsertComponents.d.ts +3 -4
  27. package/dist/types/ui/getRecommendedComponents.d.ts +8 -13
  28. package/dist/types/ui/registered-menu/QuickInsertMenuRoot.d.ts +3 -1
  29. package/dist/types/ui/registered-menu/ToolbarQuickInsertMenu.d.ts +3 -2
  30. package/dist/types/ui/registered-menu/TypeAheadQuickInsertMenu.d.ts +3 -2
  31. package/dist/types/ui/registered-menu/get-quick-insert-menu-model.d.ts +12 -2
  32. package/package.json +3 -6
  33. package/dist/cjs/ui/QuickInsertRecommendedSlot.js +0 -23
  34. package/dist/es2019/ui/QuickInsertRecommendedSlot.js +0 -18
  35. package/dist/esm/ui/QuickInsertRecommendedSlot.js +0 -16
  36. package/dist/types/ui/QuickInsertRecommendedSlot.d.ts +0 -8
@@ -51,48 +51,70 @@ var getSearchResults = function getSearchResults(matches) {
51
51
  var identity = _ref.identity;
52
52
  return identity;
53
53
  }));
54
- var tailMatches = matches.filter(function (_ref2) {
54
+ return [].concat((0, _toConsumableArray2.default)(topMatches), (0, _toConsumableArray2.default)(matches.filter(function (_ref2) {
55
55
  var identity = _ref2.identity;
56
56
  return !topMatchIdentities.has(identity);
57
- });
58
- return [].concat((0, _toConsumableArray2.default)(topMatches), (0, _toConsumableArray2.default)(tailMatches)).map(function (_ref3) {
59
- var item = _ref3.item;
60
- return item;
61
- });
62
- };
63
- var getRenderedMenuItems = function getRenderedMenuItems(section, childrenMap, surfaceContext) {
64
- var _childrenMap$get;
65
- return ((_childrenMap$get = childrenMap.get((0, _surfaceRenderer.getComponentIdentity)(section))) !== null && _childrenMap$get !== void 0 ? _childrenMap$get : []).filter(function (child) {
66
- return child.type === 'menu-item' && (0, _surfaceRenderer.willComponentRender)(child, childrenMap, surfaceContext);
67
- });
57
+ })));
68
58
  };
69
- var buildBrowseSections = function buildBrowseSections(_ref4) {
70
- var childrenMap = _ref4.childrenMap,
71
- contentSections = _ref4.contentSections,
72
- selectCategoryItems = _ref4.selectCategoryItems,
73
- surfaceContext = _ref4.surfaceContext;
74
- var sections = [];
75
- var _iterator = _createForOfIteratorHelper(contentSections),
59
+
60
+ /** Recommended uses resolved items rather than registered children. */
61
+ var readMenuSections = function readMenuSections(_ref3) {
62
+ var childrenMap = _ref3.childrenMap,
63
+ _ref3$recommendedItem = _ref3.recommendedItems,
64
+ recommendedItems = _ref3$recommendedItem === void 0 ? [] : _ref3$recommendedItem,
65
+ sections = _ref3.sections,
66
+ surfaceContext = _ref3.surfaceContext;
67
+ var renderedSections = [];
68
+ var _iterator = _createForOfIteratorHelper(sections),
76
69
  _step;
77
70
  try {
78
71
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
72
+ var _section$isHidden, _section$isHidden2, _childrenMap$get;
79
73
  var section = _step.value;
80
- var children = getRenderedMenuItems(section, childrenMap, surfaceContext);
81
- var overflowItems = children.filter(function (child) {
82
- return (0, _typeAheadIsSectionOverflowItemKey.isSectionOverflowItemKey)(child.key);
83
- });
84
- var viewMoreItem = overflowItems[overflowItems.length - 1];
85
- var items = children.filter(function (child) {
86
- return !(0, _typeAheadIsSectionOverflowItemKey.isSectionOverflowItemKey)(child.key);
87
- });
88
- if (items.length === 0) {
74
+ if (section.type !== 'menu-section') {
89
75
  continue;
90
76
  }
91
- var selectedItems = viewMoreItem !== undefined && selectCategoryItems !== undefined ? selectCategoryItems(items) : items;
92
- if (selectedItems.length < items.length && viewMoreItem !== undefined) {
93
- sections.push([section].concat((0, _toConsumableArray2.default)(selectedItems), [viewMoreItem]));
94
- } else {
95
- sections.push([section].concat((0, _toConsumableArray2.default)(selectedItems)));
77
+ if (surfaceContext ? (_section$isHidden = section.isHidden) === null || _section$isHidden === void 0 ? void 0 : _section$isHidden.call(section, {
78
+ surfaceContext: surfaceContext
79
+ }) : (_section$isHidden2 = section.isHidden) === null || _section$isHidden2 === void 0 ? void 0 : _section$isHidden2.call(section)) {
80
+ continue;
81
+ }
82
+ if (section.key === _keys.RECOMMENDED_SECTION.key) {
83
+ renderedSections.push({
84
+ section: section,
85
+ items: recommendedItems
86
+ });
87
+ continue;
88
+ }
89
+ var children = (_childrenMap$get = childrenMap.get((0, _surfaceRenderer.getComponentIdentity)(section))) !== null && _childrenMap$get !== void 0 ? _childrenMap$get : [];
90
+ var items = [];
91
+ var viewMoreItem = void 0;
92
+ var _iterator2 = _createForOfIteratorHelper(children),
93
+ _step2;
94
+ try {
95
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
96
+ var child = _step2.value;
97
+ if (child.type !== 'menu-item' || !(0, _surfaceRenderer.willComponentRender)(child, childrenMap, surfaceContext)) {
98
+ continue;
99
+ }
100
+ if ((0, _typeAheadIsSectionOverflowItemKey.isSectionOverflowItemKey)(child.key)) {
101
+ viewMoreItem !== null && viewMoreItem !== void 0 ? viewMoreItem : viewMoreItem = child;
102
+ } else {
103
+ items.push(child);
104
+ }
105
+ }
106
+ // Empty registrations are visible leaves; containers need a visible child.
107
+ } catch (err) {
108
+ _iterator2.e(err);
109
+ } finally {
110
+ _iterator2.f();
111
+ }
112
+ if (children.length === 0 || items.length > 0 || viewMoreItem) {
113
+ renderedSections.push({
114
+ section: section,
115
+ items: items,
116
+ viewMoreItem: viewMoreItem
117
+ });
96
118
  }
97
119
  }
98
120
  } catch (err) {
@@ -100,53 +122,92 @@ var buildBrowseSections = function buildBrowseSections(_ref4) {
100
122
  } finally {
101
123
  _iterator.f();
102
124
  }
125
+ return renderedSections;
126
+ };
127
+ var getOwnerSectionKey = function getOwnerSectionKey(item, isRecommendedItem) {
128
+ var _item$parents$;
129
+ return isRecommendedItem(item) ? _keys.RECOMMENDED_SECTION.key : (_item$parents$ = item.parents[0]) === null || _item$parents$ === void 0 ? void 0 : _item$parents$.key;
130
+ };
131
+ var buildBrowseSections = function buildBrowseSections(_ref4) {
132
+ var contentSections = _ref4.contentSections,
133
+ isRecommendedItem = _ref4.isRecommendedItem,
134
+ selectCategoryItems = _ref4.selectCategoryItems;
135
+ var sections = [];
136
+ var _iterator3 = _createForOfIteratorHelper(contentSections),
137
+ _step3;
138
+ try {
139
+ var _loop = function _loop() {
140
+ var _step3$value = _step3.value,
141
+ items = _step3$value.items,
142
+ section = _step3$value.section,
143
+ viewMoreItem = _step3$value.viewMoreItem;
144
+ var ownedItems = items.filter(function (item) {
145
+ return getOwnerSectionKey(item, isRecommendedItem) === section.key;
146
+ });
147
+ if (ownedItems.length === 0) {
148
+ return 1; // continue
149
+ }
150
+ var selectedItems = viewMoreItem && selectCategoryItems ? selectCategoryItems(ownedItems) : ownedItems;
151
+ sections.push([section].concat((0, _toConsumableArray2.default)(selectedItems), (0, _toConsumableArray2.default)(viewMoreItem && selectedItems.length < ownedItems.length ? [viewMoreItem] : [])));
152
+ };
153
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
154
+ if (_loop()) continue;
155
+ }
156
+ } catch (err) {
157
+ _iterator3.e(err);
158
+ } finally {
159
+ _iterator3.f();
160
+ }
103
161
  return {
104
162
  fallbackItems: [],
105
163
  sections: sections
106
164
  };
107
165
  };
108
166
  var buildSearchSections = function buildSearchSections(_ref5) {
109
- var childrenMap = _ref5.childrenMap,
110
- components = _ref5.components,
167
+ var components = _ref5.components,
111
168
  contentSections = _ref5.contentSections,
112
169
  formatMessage = _ref5.formatMessage,
170
+ isRecommendedItem = _ref5.isRecommendedItem,
113
171
  query = _ref5.query,
114
- root = _ref5.root,
115
- surfaceContext = _ref5.surfaceContext;
116
- var matches = new Map();
172
+ root = _ref5.root;
117
173
  var sourceIndexByComponent = new Map(components.map(function (component, index) {
118
174
  return [component, index];
119
175
  }));
120
- var _iterator2 = _createForOfIteratorHelper(contentSections),
121
- _step2;
176
+ var matches = new Map();
177
+ var fallbackItem;
178
+ var _iterator4 = _createForOfIteratorHelper(contentSections),
179
+ _step4;
122
180
  try {
123
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
124
- var section = _step2.value;
125
- var _iterator3 = _createForOfIteratorHelper(getRenderedMenuItems(section, childrenMap, surfaceContext)),
126
- _step3;
181
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
182
+ var _step4$value = _step4.value,
183
+ items = _step4$value.items,
184
+ section = _step4$value.section;
185
+ var sectionRank = getParentRank(section, root.key);
186
+ var _iterator5 = _createForOfIteratorHelper(items),
187
+ _step5;
127
188
  try {
128
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
189
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
129
190
  var _item$match, _match$score, _sourceIndexByCompone;
130
- var item = _step3.value;
131
- if ((0, _typeAheadIsSectionOverflowItemKey.isSectionOverflowItemKey)(item.key)) {
132
- continue;
191
+ var item = _step5.value;
192
+ if (item.key === _keys.ASK_ROVO_MENU_ITEM.key) {
193
+ fallbackItem !== null && fallbackItem !== void 0 ? fallbackItem : fallbackItem = item;
133
194
  }
134
195
  var match = (_item$match = item.match) === null || _item$match === void 0 ? void 0 : _item$match.call(item, {
135
196
  formatMessage: formatMessage,
136
197
  itemKey: item.key,
137
198
  query: query
138
199
  });
139
- if (item.match && match === null) {
200
+ if (item.match && match === null || getOwnerSectionKey(item, isRecommendedItem) !== section.key) {
140
201
  continue;
141
202
  }
142
203
  var candidate = {
143
- identity: "".concat(item.type, ":").concat(item.key),
204
+ identity: (0, _surfaceRenderer.getComponentIdentity)(item),
144
205
  item: item,
145
206
  itemRank: getParentRank(item, section.key),
146
207
  priorityGroup: (match === null || match === void 0 ? void 0 : match.priorityGroup) !== undefined && Number.isFinite(match.priorityGroup) ? match.priorityGroup : undefined,
147
208
  score: Math.min(1, Math.max(0, (_match$score = match === null || match === void 0 ? void 0 : match.score) !== null && _match$score !== void 0 ? _match$score : 0)),
148
- sourceIndex: (_sourceIndexByCompone = sourceIndexByComponent.get(item)) !== null && _sourceIndexByCompone !== void 0 ? _sourceIndexByCompone : Number.MAX_SAFE_INTEGER,
149
- sectionRank: getParentRank(section, root.key)
209
+ sectionRank: sectionRank,
210
+ sourceIndex: (_sourceIndexByCompone = sourceIndexByComponent.get(item)) !== null && _sourceIndexByCompone !== void 0 ? _sourceIndexByCompone : Number.MAX_SAFE_INTEGER
150
211
  };
151
212
  var existing = matches.get(candidate.identity);
152
213
  if (!existing || compareMatchedItems(candidate, existing) < 0) {
@@ -154,15 +215,15 @@ var buildSearchSections = function buildSearchSections(_ref5) {
154
215
  }
155
216
  }
156
217
  } catch (err) {
157
- _iterator3.e(err);
218
+ _iterator5.e(err);
158
219
  } finally {
159
- _iterator3.f();
220
+ _iterator5.f();
160
221
  }
161
222
  }
162
223
  } catch (err) {
163
- _iterator2.e(err);
224
+ _iterator4.e(err);
164
225
  } finally {
165
- _iterator2.f();
226
+ _iterator4.f();
166
227
  }
167
228
  var uniqueMatches = Array.from(matches.values()).sort(compareMatchedItems);
168
229
  var prioritizedMatches = uniqueMatches.filter(function (_ref6) {
@@ -176,44 +237,50 @@ var buildSearchSections = function buildSearchSections(_ref5) {
176
237
  var orderedSearchResults = [].concat((0, _toConsumableArray2.default)(prioritizedMatches.sort(comparePrioritizedSearchResults).map(function (_ref8) {
177
238
  var item = _ref8.item;
178
239
  return item;
179
- })), (0, _toConsumableArray2.default)(getSearchResults(unprioritizedMatches)));
240
+ })), (0, _toConsumableArray2.default)(getSearchResults(unprioritizedMatches).map(function (_ref9) {
241
+ var item = _ref9.item;
242
+ return item;
243
+ })));
180
244
  if (orderedSearchResults.length > 0) {
181
245
  return {
182
246
  fallbackItems: [],
183
247
  sections: [[SEARCH_RESULTS_HEADING].concat((0, _toConsumableArray2.default)(orderedSearchResults))]
184
248
  };
185
249
  }
186
- var fallbackItem = contentSections.flatMap(function (section) {
187
- var _childrenMap$get2;
188
- return (_childrenMap$get2 = childrenMap.get((0, _surfaceRenderer.getComponentIdentity)(section))) !== null && _childrenMap$get2 !== void 0 ? _childrenMap$get2 : [];
189
- }).find(function (component) {
190
- return component.type === _keys.ASK_ROVO_MENU_ITEM.type && component.key === _keys.ASK_ROVO_MENU_ITEM.key && (0, _surfaceRenderer.willComponentRender)(component, childrenMap, surfaceContext);
191
- });
192
250
  return {
193
251
  fallbackItems: fallbackItem ? [fallbackItem] : [],
194
252
  sections: []
195
253
  };
196
254
  };
197
255
 
256
+ /**
257
+ * Resolves the Recommended items for a browse. Receives the unranked components so a resolver
258
+ * can look recommendations up by their registered keys.
259
+ */
260
+
198
261
  /**
199
262
  * Builds the registered quick-insert menu model. An empty query browses every
200
263
  * category; a non-empty query returns ranked matches. The footer is shared by both.
201
264
  */
202
- var getQuickInsertMenuModel = exports.getQuickInsertMenuModel = function getQuickInsertMenuModel(_ref9) {
203
- var components = _ref9.components,
204
- formatMessage = _ref9.formatMessage,
205
- getItemRank = _ref9.getItemRank,
206
- query = _ref9.query,
207
- rootComponent = _ref9.rootComponent,
208
- selectCategoryItems = _ref9.selectCategoryItems,
209
- surfaceContext = _ref9.surfaceContext;
265
+ var getQuickInsertMenuModel = exports.getQuickInsertMenuModel = function getQuickInsertMenuModel(_ref0) {
266
+ var _root$isHidden, _root$isHidden2, _contentSections$find;
267
+ var components = _ref0.components,
268
+ formatMessage = _ref0.formatMessage,
269
+ getItemRank = _ref0.getItemRank,
270
+ getRecommendedItems = _ref0.getRecommendedItems,
271
+ query = _ref0.query,
272
+ rootComponent = _ref0.rootComponent,
273
+ selectCategoryItems = _ref0.selectCategoryItems,
274
+ surfaceContext = _ref0.surfaceContext;
210
275
  var rankedComponents = (0, _itemRank.applyRegisteredItemRanks)(components, getItemRank);
211
276
  var _resolveSurface = (0, _surfaceRenderer.resolveSurface)(rankedComponents, rootComponent),
212
277
  childrenMap = _resolveSurface.childrenMap,
213
278
  root = _resolveSurface.root,
214
279
  _resolveSurface$topLe = _resolveSurface.topLevelChildren,
215
280
  topLevelChildren = _resolveSurface$topLe === void 0 ? [] : _resolveSurface$topLe;
216
- if (!root || !(0, _surfaceRenderer.willComponentRender)(root, childrenMap, surfaceContext)) {
281
+ if (!root || (surfaceContext ? (_root$isHidden = root.isHidden) === null || _root$isHidden === void 0 ? void 0 : _root$isHidden.call(root, {
282
+ surfaceContext: surfaceContext
283
+ }) : (_root$isHidden2 = root.isHidden) === null || _root$isHidden2 === void 0 ? void 0 : _root$isHidden2.call(root))) {
217
284
  return {
218
285
  fallbackItems: [],
219
286
  footer: undefined,
@@ -221,32 +288,52 @@ var getQuickInsertMenuModel = exports.getQuickInsertMenuModel = function getQuic
221
288
  sections: []
222
289
  };
223
290
  }
224
- var renderedSections = topLevelChildren.filter(function (section) {
225
- return section.type === 'menu-section' && (0, _surfaceRenderer.willComponentRender)(section, childrenMap, surfaceContext);
291
+ var isBrowse = query === '';
292
+ var renderedSections = readMenuSections({
293
+ sections: topLevelChildren,
294
+ childrenMap: childrenMap,
295
+ surfaceContext: surfaceContext,
296
+ recommendedItems: isBrowse ? getRecommendedItems === null || getRecommendedItems === void 0 ? void 0 : getRecommendedItems({
297
+ components: components,
298
+ surfaceContext: surfaceContext
299
+ }) : undefined
226
300
  });
227
- var footerSection = renderedSections.find(function (_ref0) {
228
- var key = _ref0.key;
229
- return (0, _typeAheadIsMenuFooterSectionKey.isMenuFooterSectionKey)(key);
301
+ if (topLevelChildren.length > 0 && renderedSections.length === 0) {
302
+ return {
303
+ fallbackItems: [],
304
+ footer: undefined,
305
+ root: undefined,
306
+ sections: []
307
+ };
308
+ }
309
+ var footerSection = renderedSections.find(function (_ref1) {
310
+ var section = _ref1.section;
311
+ return (0, _typeAheadIsMenuFooterSectionKey.isMenuFooterSectionKey)(section.key);
230
312
  });
231
- var contentSections = renderedSections.filter(function (_ref1) {
232
- var key = _ref1.key;
233
- return !(0, _typeAheadIsMenuFooterSectionKey.isMenuFooterSectionKey)(key);
313
+ var contentSections = renderedSections.filter(function (_ref10) {
314
+ var section = _ref10.section;
315
+ return !(0, _typeAheadIsMenuFooterSectionKey.isMenuFooterSectionKey)(section.key) && (isBrowse || section.key !== _keys.RECOMMENDED_SECTION.key);
234
316
  });
235
- var content = query === '' ? buildBrowseSections({
236
- childrenMap: childrenMap,
317
+ var recommendedIdentities = new Set((_contentSections$find = contentSections.find(function (_ref11) {
318
+ var section = _ref11.section;
319
+ return section.key === _keys.RECOMMENDED_SECTION.key;
320
+ })) === null || _contentSections$find === void 0 ? void 0 : _contentSections$find.items.map(_surfaceRenderer.getComponentIdentity));
321
+ var isRecommendedItem = function isRecommendedItem(item) {
322
+ return recommendedIdentities.has((0, _surfaceRenderer.getComponentIdentity)(item));
323
+ };
324
+ var content = isBrowse ? buildBrowseSections({
237
325
  contentSections: contentSections,
238
- selectCategoryItems: selectCategoryItems,
239
- surfaceContext: surfaceContext
326
+ isRecommendedItem: isRecommendedItem,
327
+ selectCategoryItems: selectCategoryItems
240
328
  }) : buildSearchSections({
241
- childrenMap: childrenMap,
242
329
  components: rankedComponents,
243
330
  contentSections: contentSections,
244
331
  formatMessage: formatMessage,
332
+ isRecommendedItem: isRecommendedItem,
245
333
  query: query,
246
- root: root,
247
- surfaceContext: surfaceContext
334
+ root: root
248
335
  });
249
- var footer = footerSection ? getRenderedMenuItems(footerSection, childrenMap, surfaceContext)[0] : undefined;
336
+ var footer = footerSection === null || footerSection === void 0 ? void 0 : footerSection.items[0];
250
337
  return _objectSpread(_objectSpread({}, content), {}, {
251
338
  footer: footer,
252
339
  root: root
@@ -17,6 +17,7 @@ import { pluginKey } from './pm-plugins/plugin-key';
17
17
  import { getBlockControlQuickInsertComponents } from './ui/block-control-quick-insert';
18
18
  import { getLegacyCompatibleComponents } from './ui/getLegacyCompatibleComponents';
19
19
  import { getQuickInsertComponents } from './ui/getQuickInsertComponents';
20
+ import { createRecommendedItemsResolver } from './ui/getRecommendedComponents';
20
21
  import ModalElementBrowser from './ui/ModalElementBrowser';
21
22
  import { RegistryElementBrowserContainer } from './ui/RegistryElementBrowser';
22
23
  import { getQuickInsertSuggestions, withLayoutQuickInsertPrioritySorting } from './ui/search';
@@ -31,6 +32,10 @@ export const quickInsertPlugin = ({
31
32
  };
32
33
  const typeAheadPrioritySortingFn = withLayoutQuickInsertPrioritySorting(options === null || options === void 0 ? void 0 : options.prioritySortingFn);
33
34
  const getItemRank = createQuickInsertRankResolver(options === null || options === void 0 ? void 0 : options.getItemRank);
35
+ const getRecommendedItems = createRecommendedItemsResolver({
36
+ isRecommendedItem: options === null || options === void 0 ? void 0 : options.isRecommendedItem,
37
+ maxRecommendedItems: options === null || options === void 0 ? void 0 : options.maxRecommendedItems
38
+ });
34
39
  const typeAhead = {
35
40
  id: TypeAheadAvailableNodes.QUICK_INSERT,
36
41
  registeredMenuKey: isExperimentEnabled('platform_editor_slash_command') ? MENU.key : undefined,
@@ -79,8 +84,7 @@ export const quickInsertPlugin = ({
79
84
  api === null || api === void 0 ? void 0 : (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 ? void 0 : _api$uiControlRegistr.actions.register(getQuickInsertComponents({
80
85
  api,
81
86
  getItemRank,
82
- isRecommendedItem: options === null || options === void 0 ? void 0 : options.isRecommendedItem,
83
- maxRecommendedItems: options === null || options === void 0 ? void 0 : options.maxRecommendedItems,
87
+ getRecommendedItems,
84
88
  emptyStateHandler: options === null || options === void 0 ? void 0 : options.emptyStateHandler,
85
89
  fireAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent,
86
90
  includeElementBrowserItems: (options === null || options === void 0 ? void 0 : options.enableElementBrowser) === true
@@ -5,9 +5,7 @@ import { messages } from '@atlaskit/editor-common/quick-insert/messages';
5
5
  import { CATEGORY_VIEW_MORE_RANK, QUICK_INSERT_MENU_RANK } from '@atlaskit/editor-common/quick-insert/rank';
6
6
  import { getMenuFooterSectionKey } from '@atlaskit/editor-common/type-ahead-get-menu-footer-section-key';
7
7
  import { getSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-get-section-overflow-item-key';
8
- import { createRecommendedSnapshotCache, MAX_RECOMMENDED_ITEMS, RECOMMENDED_SLOT_KEY_PREFIX } from './getRecommendedComponents';
9
8
  import { QuickInsertMenuFooterItem } from './QuickInsertMenuFooterItem';
10
- import { QuickInsertRecommendedSlot } from './QuickInsertRecommendedSlot';
11
9
  import { QuickInsertSectionOverflowMenuItem } from './QuickInsertSectionOverflowMenuItem';
12
10
  import QuickInsertMenuRoot from './registered-menu/QuickInsertMenuRoot';
13
11
  import { QuickInsertMenuSection } from './registered-menu/QuickInsertMenuSection';
@@ -58,53 +56,21 @@ const createSectionComponent = message => {
58
56
  export const getQuickInsertComponents = ({
59
57
  api,
60
58
  includeElementBrowserItems,
61
- isRecommendedItem,
62
- maxRecommendedItems,
63
59
  getItemRank,
60
+ getRecommendedItems,
64
61
  emptyStateHandler,
65
62
  fireAnalyticsEvent
66
63
  }) => {
67
- const recommendedSnapshot = createRecommendedSnapshotCache({
68
- api,
69
- isRecommendedItem,
70
- maxRecommendedItems
71
- });
72
- const recommendedSlots = Array.from({
73
- length: MAX_RECOMMENDED_ITEMS
74
- }, (_, index) => ({
75
- key: `${RECOMMENDED_SLOT_KEY_PREFIX}${index}`,
76
- type: 'menu-item',
77
- parents: [{
78
- key: RECOMMENDED_SECTION.key,
79
- type: RECOMMENDED_SECTION.type,
80
- rank: index
81
- }],
82
- match: () => null,
83
- isHidden: ({
84
- surfaceContext
85
- } = {}) => !recommendedSnapshot.getSnapshot(surfaceContext)[index],
86
- component: ({
87
- children,
88
- parents,
89
- surfaceContext
90
- }) => /*#__PURE__*/React.createElement(QuickInsertRecommendedSlot, {
91
- parents: parents,
92
- surfaceContext: surfaceContext,
93
- index: index,
94
- getSnapshot: recommendedSnapshot.getSnapshot
95
- }, children)
96
- }));
97
64
  return [{
98
65
  key: MENU.key,
99
66
  type: MENU.type,
100
- component: ({
101
- children
102
- }) => /*#__PURE__*/React.createElement(QuickInsertMenuRoot, {
67
+ component: () => /*#__PURE__*/React.createElement(QuickInsertMenuRoot, {
103
68
  getItemRank: getItemRank,
69
+ getRecommendedItems: getRecommendedItems,
104
70
  emptyStateHandler: emptyStateHandler,
105
71
  fireAnalyticsEvent: fireAnalyticsEvent
106
- }, children)
107
- }, ...recommendedSlots, ...categories.flatMap(({
72
+ })
73
+ }, ...categories.flatMap(({
108
74
  message,
109
75
  section
110
76
  }) => [{
@@ -115,10 +81,7 @@ export const getQuickInsertComponents = ({
115
81
  type: MENU.type,
116
82
  rank: QUICK_INSERT_MENU_RANK[section.key]
117
83
  }],
118
- component: createSectionComponent(message),
119
- isHidden: section.key === RECOMMENDED_SECTION.key ? ({
120
- surfaceContext
121
- } = {}) => recommendedSnapshot.getSnapshot(surfaceContext).length === 0 : undefined
84
+ component: createSectionComponent(message)
122
85
  }, ...(includeElementBrowserItems && section.key !== RECOMMENDED_SECTION.key ? [{
123
86
  key: getSectionOverflowItemKey(section.key),
124
87
  type: 'menu-item',
@@ -1,22 +1,18 @@
1
1
  import { logException } from '@atlaskit/editor-common/monitoring/error';
2
2
  import { quickInsertProviderMenuItemKey } from '@atlaskit/editor-common/quick-insert/get-provider-menu-item-key';
3
3
  import { defaultIsRecommendedItem } from '@atlaskit/editor-common/quick-insert/is-recommended-item';
4
- import { MENU } from '@atlaskit/editor-common/quick-insert/keys';
5
- import { REGISTERED_MENU_SURFACE_CONTEXT } from '@atlaskit/editor-common/registered-menu/surface-context';
6
4
  import { isMenuFooterSectionKey } from '@atlaskit/editor-common/type-ahead-is-menu-footer-section-key';
7
5
  import { isSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-is-section-overflow-item-key';
8
6
  export const MAX_RECOMMENDED_ITEMS = 5;
9
- export const RECOMMENDED_SLOT_KEY_PREFIX = 'quick-insert-recommended-slot-';
10
- export const isRecommendedSlotKey = key => key.startsWith(RECOMMENDED_SLOT_KEY_PREFIX);
11
- const isRecommendationCandidate = component => component.type === 'menu-item' && !isRecommendedSlotKey(component.key) && !isSectionOverflowItemKey(component.key) && !component.parents.some(parent => isMenuFooterSectionKey(parent.key));
7
+ const isRecommendationCandidate = component => component.type === 'menu-item' && !isSectionOverflowItemKey(component.key) && !component.parents.some(parent => isMenuFooterSectionKey(parent.key));
12
8
 
13
- /** Normalises a consumer-supplied limit to the number of available recommended slots. */
9
+ /** Normalises a consumer-supplied limit to the supported number of recommended items. */
14
10
  export const resolveMaxRecommendedItems = maxRecommendedItems => {
15
11
  if (maxRecommendedItems === undefined || !Number.isFinite(maxRecommendedItems)) {
16
12
  return MAX_RECOMMENDED_ITEMS;
17
13
  }
18
14
  if (maxRecommendedItems > MAX_RECOMMENDED_ITEMS) {
19
- void logException(new Error('Quick Insert maxRecommendedItems exceeds the available slots'), {
15
+ void logException(new Error('Quick Insert maxRecommendedItems exceeds the supported maximum'), {
20
16
  location: 'editor-plugin-quick-insert/getRecommendedComponents'
21
17
  });
22
18
  }
@@ -58,35 +54,19 @@ export const getRecommendedComponents = ({
58
54
  }) => component);
59
55
  };
60
56
 
61
- /** Keeps only the current menu-open recommendation snapshot. */
62
-
63
- export const createRecommendedSnapshotCache = ({
64
- api,
57
+ /**
58
+ * Resolves the Recommended section for a browse-mode menu. Callers memoise per components array,
59
+ * so the resolver itself keeps no state.
60
+ */
61
+ export const createRecommendedItemsResolver = ({
65
62
  isRecommendedItem,
66
63
  maxRecommendedItems
67
- }) => {
68
- let snapshot;
69
- const getSnapshot = surfaceContext => {
70
- var _surfaceContext$get, _snapshot;
71
- const menuOpenId = surfaceContext === null || surfaceContext === void 0 ? void 0 : (_surfaceContext$get = surfaceContext.get(REGISTERED_MENU_SURFACE_CONTEXT)) === null || _surfaceContext$get === void 0 ? void 0 : _surfaceContext$get.menuOpenId;
72
- if (!surfaceContext || !menuOpenId) {
73
- return [];
74
- }
75
- if (((_snapshot = snapshot) === null || _snapshot === void 0 ? void 0 : _snapshot.id) !== menuOpenId) {
76
- var _api$uiControlRegistr, _api$uiControlRegistr2;
77
- snapshot = {
78
- id: menuOpenId,
79
- items: getRecommendedComponents({
80
- components: (_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [],
81
- context: surfaceContext,
82
- isRecommendedItem,
83
- maxRecommendedItems
84
- })
85
- };
86
- }
87
- return snapshot.items;
88
- };
89
- return {
90
- getSnapshot
91
- };
92
- };
64
+ }) => ({
65
+ components,
66
+ surfaceContext
67
+ }) => surfaceContext ? getRecommendedComponents({
68
+ components,
69
+ context: surfaceContext,
70
+ isRecommendedItem,
71
+ maxRecommendedItems
72
+ }) : [];
@@ -21,7 +21,8 @@ const isImeEnter = event => event.isComposing || event.keyCode === 229;
21
21
  const QuickInsertMenuRoot = ({
22
22
  emptyStateHandler,
23
23
  fireAnalyticsEvent,
24
- getItemRank
24
+ getItemRank,
25
+ getRecommendedItems
25
26
  }) => {
26
27
  var _surfaceContext$get, _registeredMenu$maxHe;
27
28
  const registeredMenu = useRegisteredMenuContext();
@@ -46,13 +47,14 @@ const QuickInsertMenuRoot = ({
46
47
  components,
47
48
  formatMessage,
48
49
  getItemRank: runtimeItemRank !== null && runtimeItemRank !== void 0 ? runtimeItemRank : getItemRank,
50
+ getRecommendedItems,
49
51
  query,
50
52
  rootComponent,
51
53
  selectCategoryItems: components.some(({
52
54
  key
53
55
  }) => isSectionOverflowItemKey(key)) ? selectQuickInsertCategoryItems : undefined,
54
56
  surfaceContext
55
- }), [components, formatMessage, getItemRank, query, rootComponent, runtimeItemRank, surfaceContext]);
57
+ }), [components, formatMessage, getItemRank, getRecommendedItems, query, rootComponent, runtimeItemRank, surfaceContext]);
56
58
  const resultCount = useMemo(() => model.sections.reduce((count, [, ...items]) => count + items.filter(({
57
59
  key
58
60
  }) => !isSectionOverflowItemKey(key)).length, 0), [model.sections]);
@@ -82,6 +84,7 @@ const QuickInsertMenuRoot = ({
82
84
  selectableItems,
83
85
  selectedItemIndex,
84
86
  activeItemKey,
87
+ selectionSource,
85
88
  ...listEvents
86
89
  } = useRegisteredMenu({
87
90
  model,
@@ -167,7 +170,8 @@ const QuickInsertMenuRoot = ({
167
170
  onRenderedItemsChange: setRenderedItems,
168
171
  query: query,
169
172
  rows: rows,
170
- selectedItemIndex: selectedItemIndex
173
+ selectedItemIndex: selectedItemIndex,
174
+ selectionSource: selectionSource
171
175
  }) : /*#__PURE__*/React.createElement(ToolbarQuickInsertMenu, {
172
176
  Item: RegisteredQuickInsertMenuItem,
173
177
  activePreviewItemKey: activeItemKey,
@@ -185,7 +189,8 @@ const QuickInsertMenuRoot = ({
185
189
  onRenderedItemsChange: setRenderedItems,
186
190
  query: query,
187
191
  rows: rows,
188
- selectedItemIndex: selectedItemIndex
192
+ selectedItemIndex: selectedItemIndex,
193
+ selectionSource: selectionSource
189
194
  }))));
190
195
  };
191
196
  export default QuickInsertMenuRoot;
@@ -7,7 +7,6 @@ export const RegisteredQuickInsertMenuItem = ({
7
7
  isActive,
8
8
  registration
9
9
  }) => {
10
- var _registration$compone;
11
10
  const {
12
11
  editorView,
13
12
  isOffline,
@@ -27,8 +26,11 @@ export const RegisteredQuickInsertMenuItem = ({
27
26
  select,
28
27
  surfaceContext
29
28
  }), [editorView, isOffline, popupsMountPoint, select, surfaceContext, isActive, id, isSelected]);
30
- const Component = (_registration$compone = registration.component) !== null && _registration$compone !== void 0 ? _registration$compone : React.Fragment;
29
+ const Component = registration.component;
31
30
  return /*#__PURE__*/React.createElement(QuickInsertProvider, {
32
31
  value: value
33
- }, /*#__PURE__*/React.createElement(Component, null, null));
32
+ }, Component ? /*#__PURE__*/React.createElement(Component, {
33
+ parents: registration.parents,
34
+ surfaceContext: surfaceContext
35
+ }, null) : null);
34
36
  };
@@ -32,7 +32,8 @@ export const ToolbarQuickInsertMenu = ({
32
32
  onItemVisibilityChange,
33
33
  onRenderedItemsChange,
34
34
  query,
35
- selectedItemIndex
35
+ selectedItemIndex,
36
+ selectionSource
36
37
  }) => {
37
38
  const footerItemIndex = itemCount - 1;
38
39
  const footerItemId = getQuickInsertMenuItemId(listId, footerItemIndex);
@@ -79,6 +80,7 @@ export const ToolbarQuickInsertMenu = ({
79
80
  getItemId: getItemId,
80
81
  activeItemKey: activePreviewItemKey,
81
82
  selectedItemIndex: selectedItemIndex,
83
+ selectionSource: selectionSource,
82
84
  scrollResetKey: query,
83
85
  onItemHover: onItemHover,
84
86
  onItemFocus: onItemFocus,