@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
@@ -29,6 +29,7 @@ export const TypeAheadQuickInsertMenu = ({
29
29
  onRenderedItemsChange,
30
30
  query = '',
31
31
  selectedItemIndex,
32
+ selectionSource,
32
33
  hasScrollPadding = false
33
34
  }) => {
34
35
  const footerItemIndex = itemCount - 1;
@@ -53,6 +54,7 @@ export const TypeAheadQuickInsertMenu = ({
53
54
  getItemId: getItemId,
54
55
  activeItemKey: activeItemKey,
55
56
  selectedItemIndex: selectedItemIndex,
57
+ selectionSource: selectionSource,
56
58
  scrollResetKey: query,
57
59
  hasScrollPadding: hasScrollPadding,
58
60
  scrollTo: "top-on-reset",
@@ -1,4 +1,4 @@
1
- import { ASK_ROVO_MENU_ITEM, MENU, SEARCH_RESULTS_SECTION } from '@atlaskit/editor-common/quick-insert/keys';
1
+ import { ASK_ROVO_MENU_ITEM, MENU, RECOMMENDED_SECTION, SEARCH_RESULTS_SECTION } from '@atlaskit/editor-common/quick-insert/keys';
2
2
  import { applyRegisteredItemRanks } from '@atlaskit/editor-common/registered-menu/item-rank';
3
3
  import { isMenuFooterSectionKey } from '@atlaskit/editor-common/type-ahead-is-menu-footer-section-key';
4
4
  import { isSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-is-section-overflow-item-key';
@@ -30,38 +30,81 @@ const getSearchResults = matches => {
30
30
  const topMatchIdentities = new Set(topMatches.map(({
31
31
  identity
32
32
  }) => identity));
33
- const tailMatches = matches.filter(({
33
+ return [...topMatches, ...matches.filter(({
34
34
  identity
35
- }) => !topMatchIdentities.has(identity));
36
- return [...topMatches, ...tailMatches].map(({
37
- item
38
- }) => item);
35
+ }) => !topMatchIdentities.has(identity))];
39
36
  };
40
- const getRenderedMenuItems = (section, childrenMap, surfaceContext) => {
41
- var _childrenMap$get;
42
- return ((_childrenMap$get = childrenMap.get(getComponentIdentity(section))) !== null && _childrenMap$get !== void 0 ? _childrenMap$get : []).filter(child => child.type === 'menu-item' && willComponentRender(child, childrenMap, surfaceContext));
37
+
38
+ /** Recommended uses resolved items rather than registered children. */
39
+ const readMenuSections = ({
40
+ childrenMap,
41
+ recommendedItems = [],
42
+ sections,
43
+ surfaceContext
44
+ }) => {
45
+ const renderedSections = [];
46
+ for (const section of sections) {
47
+ var _section$isHidden, _section$isHidden2, _childrenMap$get;
48
+ if (section.type !== 'menu-section') {
49
+ continue;
50
+ }
51
+ if (surfaceContext ? (_section$isHidden = section.isHidden) === null || _section$isHidden === void 0 ? void 0 : _section$isHidden.call(section, {
52
+ surfaceContext
53
+ }) : (_section$isHidden2 = section.isHidden) === null || _section$isHidden2 === void 0 ? void 0 : _section$isHidden2.call(section)) {
54
+ continue;
55
+ }
56
+ if (section.key === RECOMMENDED_SECTION.key) {
57
+ renderedSections.push({
58
+ section,
59
+ items: recommendedItems
60
+ });
61
+ continue;
62
+ }
63
+ const children = (_childrenMap$get = childrenMap.get(getComponentIdentity(section))) !== null && _childrenMap$get !== void 0 ? _childrenMap$get : [];
64
+ const items = [];
65
+ let viewMoreItem;
66
+ for (const child of children) {
67
+ if (child.type !== 'menu-item' || !willComponentRender(child, childrenMap, surfaceContext)) {
68
+ continue;
69
+ }
70
+ if (isSectionOverflowItemKey(child.key)) {
71
+ viewMoreItem ??= child;
72
+ } else {
73
+ items.push(child);
74
+ }
75
+ }
76
+ // Empty registrations are visible leaves; containers need a visible child.
77
+ if (children.length === 0 || items.length > 0 || viewMoreItem) {
78
+ renderedSections.push({
79
+ section,
80
+ items,
81
+ viewMoreItem
82
+ });
83
+ }
84
+ }
85
+ return renderedSections;
86
+ };
87
+ const getOwnerSectionKey = (item, isRecommendedItem) => {
88
+ var _item$parents$;
89
+ return isRecommendedItem(item) ? RECOMMENDED_SECTION.key : (_item$parents$ = item.parents[0]) === null || _item$parents$ === void 0 ? void 0 : _item$parents$.key;
43
90
  };
44
91
  const buildBrowseSections = ({
45
- childrenMap,
46
92
  contentSections,
47
- selectCategoryItems,
48
- surfaceContext
93
+ isRecommendedItem,
94
+ selectCategoryItems
49
95
  }) => {
50
96
  const sections = [];
51
- for (const section of contentSections) {
52
- const children = getRenderedMenuItems(section, childrenMap, surfaceContext);
53
- const overflowItems = children.filter(child => isSectionOverflowItemKey(child.key));
54
- const viewMoreItem = overflowItems[overflowItems.length - 1];
55
- const items = children.filter(child => !isSectionOverflowItemKey(child.key));
56
- if (items.length === 0) {
97
+ for (const {
98
+ items,
99
+ section,
100
+ viewMoreItem
101
+ } of contentSections) {
102
+ const ownedItems = items.filter(item => getOwnerSectionKey(item, isRecommendedItem) === section.key);
103
+ if (ownedItems.length === 0) {
57
104
  continue;
58
105
  }
59
- const selectedItems = viewMoreItem !== undefined && selectCategoryItems !== undefined ? selectCategoryItems(items) : items;
60
- if (selectedItems.length < items.length && viewMoreItem !== undefined) {
61
- sections.push([section, ...selectedItems, viewMoreItem]);
62
- } else {
63
- sections.push([section, ...selectedItems]);
64
- }
106
+ const selectedItems = viewMoreItem && selectCategoryItems ? selectCategoryItems(ownedItems) : ownedItems;
107
+ sections.push([section, ...selectedItems, ...(viewMoreItem && selectedItems.length < ownedItems.length ? [viewMoreItem] : [])]);
65
108
  }
66
109
  return {
67
110
  fallbackItems: [],
@@ -69,38 +112,42 @@ const buildBrowseSections = ({
69
112
  };
70
113
  };
71
114
  const buildSearchSections = ({
72
- childrenMap,
73
115
  components,
74
116
  contentSections,
75
117
  formatMessage,
118
+ isRecommendedItem,
76
119
  query,
77
- root,
78
- surfaceContext
120
+ root
79
121
  }) => {
80
- const matches = new Map();
81
122
  const sourceIndexByComponent = new Map(components.map((component, index) => [component, index]));
82
- for (const section of contentSections) {
83
- for (const item of getRenderedMenuItems(section, childrenMap, surfaceContext)) {
123
+ const matches = new Map();
124
+ let fallbackItem;
125
+ for (const {
126
+ items,
127
+ section
128
+ } of contentSections) {
129
+ const sectionRank = getParentRank(section, root.key);
130
+ for (const item of items) {
84
131
  var _item$match, _match$score, _sourceIndexByCompone;
85
- if (isSectionOverflowItemKey(item.key)) {
86
- continue;
132
+ if (item.key === ASK_ROVO_MENU_ITEM.key) {
133
+ fallbackItem ??= item;
87
134
  }
88
135
  const match = (_item$match = item.match) === null || _item$match === void 0 ? void 0 : _item$match.call(item, {
89
136
  formatMessage,
90
137
  itemKey: item.key,
91
138
  query
92
139
  });
93
- if (item.match && match === null) {
140
+ if (item.match && match === null || getOwnerSectionKey(item, isRecommendedItem) !== section.key) {
94
141
  continue;
95
142
  }
96
143
  const candidate = {
97
- identity: `${item.type}:${item.key}`,
144
+ identity: getComponentIdentity(item),
98
145
  item,
99
146
  itemRank: getParentRank(item, section.key),
100
147
  priorityGroup: (match === null || match === void 0 ? void 0 : match.priorityGroup) !== undefined && Number.isFinite(match.priorityGroup) ? match.priorityGroup : undefined,
101
148
  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)),
102
- sourceIndex: (_sourceIndexByCompone = sourceIndexByComponent.get(item)) !== null && _sourceIndexByCompone !== void 0 ? _sourceIndexByCompone : Number.MAX_SAFE_INTEGER,
103
- sectionRank: getParentRank(section, root.key)
149
+ sectionRank,
150
+ sourceIndex: (_sourceIndexByCompone = sourceIndexByComponent.get(item)) !== null && _sourceIndexByCompone !== void 0 ? _sourceIndexByCompone : Number.MAX_SAFE_INTEGER
104
151
  };
105
152
  const existing = matches.get(candidate.identity);
106
153
  if (!existing || compareMatchedItems(candidate, existing) < 0) {
@@ -117,23 +164,26 @@ const buildSearchSections = ({
117
164
  }) => priorityGroup === undefined);
118
165
  const orderedSearchResults = [...prioritizedMatches.sort(comparePrioritizedSearchResults).map(({
119
166
  item
120
- }) => item), ...getSearchResults(unprioritizedMatches)];
167
+ }) => item), ...getSearchResults(unprioritizedMatches).map(({
168
+ item
169
+ }) => item)];
121
170
  if (orderedSearchResults.length > 0) {
122
171
  return {
123
172
  fallbackItems: [],
124
173
  sections: [[SEARCH_RESULTS_HEADING, ...orderedSearchResults]]
125
174
  };
126
175
  }
127
- const fallbackItem = contentSections.flatMap(section => {
128
- var _childrenMap$get2;
129
- return (_childrenMap$get2 = childrenMap.get(getComponentIdentity(section))) !== null && _childrenMap$get2 !== void 0 ? _childrenMap$get2 : [];
130
- }).find(component => component.type === ASK_ROVO_MENU_ITEM.type && component.key === ASK_ROVO_MENU_ITEM.key && willComponentRender(component, childrenMap, surfaceContext));
131
176
  return {
132
177
  fallbackItems: fallbackItem ? [fallbackItem] : [],
133
178
  sections: []
134
179
  };
135
180
  };
136
181
 
182
+ /**
183
+ * Resolves the Recommended items for a browse. Receives the unranked components so a resolver
184
+ * can look recommendations up by their registered keys.
185
+ */
186
+
137
187
  /**
138
188
  * Builds the registered quick-insert menu model. An empty query browses every
139
189
  * category; a non-empty query returns ranked matches. The footer is shared by both.
@@ -142,18 +192,40 @@ export const getQuickInsertMenuModel = ({
142
192
  components,
143
193
  formatMessage,
144
194
  getItemRank,
195
+ getRecommendedItems,
145
196
  query,
146
197
  rootComponent,
147
198
  selectCategoryItems,
148
199
  surfaceContext
149
200
  }) => {
201
+ var _root$isHidden, _root$isHidden2, _contentSections$find;
150
202
  const rankedComponents = applyRegisteredItemRanks(components, getItemRank);
151
203
  const {
152
204
  childrenMap,
153
205
  root,
154
206
  topLevelChildren = []
155
207
  } = resolveSurface(rankedComponents, rootComponent);
156
- if (!root || !willComponentRender(root, childrenMap, surfaceContext)) {
208
+ if (!root || (surfaceContext ? (_root$isHidden = root.isHidden) === null || _root$isHidden === void 0 ? void 0 : _root$isHidden.call(root, {
209
+ surfaceContext
210
+ }) : (_root$isHidden2 = root.isHidden) === null || _root$isHidden2 === void 0 ? void 0 : _root$isHidden2.call(root))) {
211
+ return {
212
+ fallbackItems: [],
213
+ footer: undefined,
214
+ root: undefined,
215
+ sections: []
216
+ };
217
+ }
218
+ const isBrowse = query === '';
219
+ const renderedSections = readMenuSections({
220
+ sections: topLevelChildren,
221
+ childrenMap,
222
+ surfaceContext,
223
+ recommendedItems: isBrowse ? getRecommendedItems === null || getRecommendedItems === void 0 ? void 0 : getRecommendedItems({
224
+ components,
225
+ surfaceContext
226
+ }) : undefined
227
+ });
228
+ if (topLevelChildren.length > 0 && renderedSections.length === 0) {
157
229
  return {
158
230
  fallbackItems: [],
159
231
  footer: undefined,
@@ -161,28 +233,29 @@ export const getQuickInsertMenuModel = ({
161
233
  sections: []
162
234
  };
163
235
  }
164
- const renderedSections = topLevelChildren.filter(section => section.type === 'menu-section' && willComponentRender(section, childrenMap, surfaceContext));
165
236
  const footerSection = renderedSections.find(({
166
- key
167
- }) => isMenuFooterSectionKey(key));
237
+ section
238
+ }) => isMenuFooterSectionKey(section.key));
168
239
  const contentSections = renderedSections.filter(({
169
- key
170
- }) => !isMenuFooterSectionKey(key));
171
- const content = query === '' ? buildBrowseSections({
172
- childrenMap,
240
+ section
241
+ }) => !isMenuFooterSectionKey(section.key) && (isBrowse || section.key !== RECOMMENDED_SECTION.key));
242
+ const recommendedIdentities = new Set((_contentSections$find = contentSections.find(({
243
+ section
244
+ }) => section.key === RECOMMENDED_SECTION.key)) === null || _contentSections$find === void 0 ? void 0 : _contentSections$find.items.map(getComponentIdentity));
245
+ const isRecommendedItem = item => recommendedIdentities.has(getComponentIdentity(item));
246
+ const content = isBrowse ? buildBrowseSections({
173
247
  contentSections,
174
- selectCategoryItems,
175
- surfaceContext
248
+ isRecommendedItem,
249
+ selectCategoryItems
176
250
  }) : buildSearchSections({
177
- childrenMap,
178
251
  components: rankedComponents,
179
252
  contentSections,
180
253
  formatMessage,
254
+ isRecommendedItem,
181
255
  query,
182
- root,
183
- surfaceContext
256
+ root
184
257
  });
185
- const footer = footerSection ? getRenderedMenuItems(footerSection, childrenMap, surfaceContext)[0] : undefined;
258
+ const footer = footerSection === null || footerSection === void 0 ? void 0 : footerSection.items[0];
186
259
  return {
187
260
  ...content,
188
261
  footer,
@@ -23,6 +23,7 @@ import { pluginKey } from './pm-plugins/plugin-key';
23
23
  import { getBlockControlQuickInsertComponents } from './ui/block-control-quick-insert';
24
24
  import { getLegacyCompatibleComponents } from './ui/getLegacyCompatibleComponents';
25
25
  import { getQuickInsertComponents } from './ui/getQuickInsertComponents';
26
+ import { createRecommendedItemsResolver } from './ui/getRecommendedComponents';
26
27
  import ModalElementBrowser from './ui/ModalElementBrowser';
27
28
  import { RegistryElementBrowserContainer } from './ui/RegistryElementBrowser';
28
29
  import { getQuickInsertSuggestions, withLayoutQuickInsertPrioritySorting } from './ui/search';
@@ -36,6 +37,10 @@ export var quickInsertPlugin = function quickInsertPlugin(_ref) {
36
37
  };
37
38
  var typeAheadPrioritySortingFn = withLayoutQuickInsertPrioritySorting(options === null || options === void 0 ? void 0 : options.prioritySortingFn);
38
39
  var getItemRank = createQuickInsertRankResolver(options === null || options === void 0 ? void 0 : options.getItemRank);
40
+ var getRecommendedItems = createRecommendedItemsResolver({
41
+ isRecommendedItem: options === null || options === void 0 ? void 0 : options.isRecommendedItem,
42
+ maxRecommendedItems: options === null || options === void 0 ? void 0 : options.maxRecommendedItems
43
+ });
39
44
  var typeAhead = {
40
45
  id: TypeAheadAvailableNodes.QUICK_INSERT,
41
46
  registeredMenuKey: isExperimentEnabled('platform_editor_slash_command') ? MENU.key : undefined,
@@ -84,8 +89,7 @@ export var quickInsertPlugin = function quickInsertPlugin(_ref) {
84
89
  api === null || api === void 0 || (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 || _api$uiControlRegistr.actions.register(getQuickInsertComponents({
85
90
  api: api,
86
91
  getItemRank: getItemRank,
87
- isRecommendedItem: options === null || options === void 0 ? void 0 : options.isRecommendedItem,
88
- maxRecommendedItems: options === null || options === void 0 ? void 0 : options.maxRecommendedItems,
92
+ getRecommendedItems: getRecommendedItems,
89
93
  emptyStateHandler: options === null || options === void 0 ? void 0 : options.emptyStateHandler,
90
94
  fireAnalyticsEvent: api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent,
91
95
  includeElementBrowserItems: (options === null || options === void 0 ? void 0 : options.enableElementBrowser) === true
@@ -6,9 +6,7 @@ import { messages } from '@atlaskit/editor-common/quick-insert/messages';
6
6
  import { CATEGORY_VIEW_MORE_RANK, QUICK_INSERT_MENU_RANK } from '@atlaskit/editor-common/quick-insert/rank';
7
7
  import { getMenuFooterSectionKey } from '@atlaskit/editor-common/type-ahead-get-menu-footer-section-key';
8
8
  import { getSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-get-section-overflow-item-key';
9
- import { createRecommendedSnapshotCache, MAX_RECOMMENDED_ITEMS, RECOMMENDED_SLOT_KEY_PREFIX } from './getRecommendedComponents';
10
9
  import { QuickInsertMenuFooterItem } from './QuickInsertMenuFooterItem';
11
- import { QuickInsertRecommendedSlot } from './QuickInsertRecommendedSlot';
12
10
  import { QuickInsertSectionOverflowMenuItem } from './QuickInsertSectionOverflowMenuItem';
13
11
  import QuickInsertMenuRoot from './registered-menu/QuickInsertMenuRoot';
14
12
  import { QuickInsertMenuSection } from './registered-menu/QuickInsertMenuSection';
@@ -57,62 +55,24 @@ var createSectionComponent = function createSectionComponent(message) {
57
55
  export var getQuickInsertComponents = function getQuickInsertComponents(_ref2) {
58
56
  var api = _ref2.api,
59
57
  includeElementBrowserItems = _ref2.includeElementBrowserItems,
60
- isRecommendedItem = _ref2.isRecommendedItem,
61
- maxRecommendedItems = _ref2.maxRecommendedItems,
62
58
  getItemRank = _ref2.getItemRank,
59
+ getRecommendedItems = _ref2.getRecommendedItems,
63
60
  emptyStateHandler = _ref2.emptyStateHandler,
64
61
  fireAnalyticsEvent = _ref2.fireAnalyticsEvent;
65
- var recommendedSnapshot = createRecommendedSnapshotCache({
66
- api: api,
67
- isRecommendedItem: isRecommendedItem,
68
- maxRecommendedItems: maxRecommendedItems
69
- });
70
- var recommendedSlots = Array.from({
71
- length: MAX_RECOMMENDED_ITEMS
72
- }, function (_, index) {
73
- return {
74
- key: "".concat(RECOMMENDED_SLOT_KEY_PREFIX).concat(index),
75
- type: 'menu-item',
76
- parents: [{
77
- key: RECOMMENDED_SECTION.key,
78
- type: RECOMMENDED_SECTION.type,
79
- rank: index
80
- }],
81
- match: function match() {
82
- return null;
83
- },
84
- isHidden: function isHidden() {
85
- var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
86
- surfaceContext = _ref3.surfaceContext;
87
- return !recommendedSnapshot.getSnapshot(surfaceContext)[index];
88
- },
89
- component: function component(_ref4) {
90
- var children = _ref4.children,
91
- parents = _ref4.parents,
92
- surfaceContext = _ref4.surfaceContext;
93
- return /*#__PURE__*/React.createElement(QuickInsertRecommendedSlot, {
94
- parents: parents,
95
- surfaceContext: surfaceContext,
96
- index: index,
97
- getSnapshot: recommendedSnapshot.getSnapshot
98
- }, children);
99
- }
100
- };
101
- });
102
62
  return [{
103
63
  key: MENU.key,
104
64
  type: MENU.type,
105
- component: function component(_ref5) {
106
- var children = _ref5.children;
65
+ component: function component() {
107
66
  return /*#__PURE__*/React.createElement(QuickInsertMenuRoot, {
108
67
  getItemRank: getItemRank,
68
+ getRecommendedItems: getRecommendedItems,
109
69
  emptyStateHandler: emptyStateHandler,
110
70
  fireAnalyticsEvent: fireAnalyticsEvent
111
- }, children);
71
+ });
112
72
  }
113
- }].concat(recommendedSlots, _toConsumableArray(categories.flatMap(function (_ref6) {
114
- var message = _ref6.message,
115
- section = _ref6.section;
73
+ }].concat(_toConsumableArray(categories.flatMap(function (_ref3) {
74
+ var message = _ref3.message,
75
+ section = _ref3.section;
116
76
  return [{
117
77
  key: section.key,
118
78
  type: section.type,
@@ -121,12 +81,7 @@ export var getQuickInsertComponents = function getQuickInsertComponents(_ref2) {
121
81
  type: MENU.type,
122
82
  rank: QUICK_INSERT_MENU_RANK[section.key]
123
83
  }],
124
- component: createSectionComponent(message),
125
- isHidden: section.key === RECOMMENDED_SECTION.key ? function () {
126
- var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
127
- surfaceContext = _ref7.surfaceContext;
128
- return recommendedSnapshot.getSnapshot(surfaceContext).length === 0;
129
- } : undefined
84
+ component: createSectionComponent(message)
130
85
  }].concat(_toConsumableArray(includeElementBrowserItems && section.key !== RECOMMENDED_SECTION.key ? [{
131
86
  key: getSectionOverflowItemKey(section.key),
132
87
  type: 'menu-item',
@@ -1,28 +1,22 @@
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 var MAX_RECOMMENDED_ITEMS = 5;
9
- export var RECOMMENDED_SLOT_KEY_PREFIX = 'quick-insert-recommended-slot-';
10
- export var isRecommendedSlotKey = function isRecommendedSlotKey(key) {
11
- return key.startsWith(RECOMMENDED_SLOT_KEY_PREFIX);
12
- };
13
7
  var isRecommendationCandidate = function isRecommendationCandidate(component) {
14
- return component.type === 'menu-item' && !isRecommendedSlotKey(component.key) && !isSectionOverflowItemKey(component.key) && !component.parents.some(function (parent) {
8
+ return component.type === 'menu-item' && !isSectionOverflowItemKey(component.key) && !component.parents.some(function (parent) {
15
9
  return isMenuFooterSectionKey(parent.key);
16
10
  });
17
11
  };
18
12
 
19
- /** Normalises a consumer-supplied limit to the number of available recommended slots. */
13
+ /** Normalises a consumer-supplied limit to the supported number of recommended items. */
20
14
  export var resolveMaxRecommendedItems = function resolveMaxRecommendedItems(maxRecommendedItems) {
21
15
  if (maxRecommendedItems === undefined || !Number.isFinite(maxRecommendedItems)) {
22
16
  return MAX_RECOMMENDED_ITEMS;
23
17
  }
24
18
  if (maxRecommendedItems > MAX_RECOMMENDED_ITEMS) {
25
- void logException(new Error('Quick Insert maxRecommendedItems exceeds the available slots'), {
19
+ void logException(new Error('Quick Insert maxRecommendedItems exceeds the supported maximum'), {
26
20
  location: 'editor-plugin-quick-insert/getRecommendedComponents'
27
21
  });
28
22
  }
@@ -67,34 +61,21 @@ export var getRecommendedComponents = function getRecommendedComponents(_ref) {
67
61
  });
68
62
  };
69
63
 
70
- /** Keeps only the current menu-open recommendation snapshot. */
71
-
72
- export var createRecommendedSnapshotCache = function createRecommendedSnapshotCache(_ref3) {
73
- var api = _ref3.api,
74
- isRecommendedItem = _ref3.isRecommendedItem,
64
+ /**
65
+ * Resolves the Recommended section for a browse-mode menu. Callers memoise per components array,
66
+ * so the resolver itself keeps no state.
67
+ */
68
+ export var createRecommendedItemsResolver = function createRecommendedItemsResolver(_ref3) {
69
+ var isRecommendedItem = _ref3.isRecommendedItem,
75
70
  maxRecommendedItems = _ref3.maxRecommendedItems;
76
- var snapshot;
77
- var getSnapshot = function getSnapshot(surfaceContext) {
78
- var _surfaceContext$get, _snapshot;
79
- var menuOpenId = surfaceContext === null || surfaceContext === void 0 || (_surfaceContext$get = surfaceContext.get(REGISTERED_MENU_SURFACE_CONTEXT)) === null || _surfaceContext$get === void 0 ? void 0 : _surfaceContext$get.menuOpenId;
80
- if (!surfaceContext || !menuOpenId) {
81
- return [];
82
- }
83
- if (((_snapshot = snapshot) === null || _snapshot === void 0 ? void 0 : _snapshot.id) !== menuOpenId) {
84
- var _api$uiControlRegistr, _api$uiControlRegistr2;
85
- snapshot = {
86
- id: menuOpenId,
87
- items: getRecommendedComponents({
88
- components: (_api$uiControlRegistr = api === null || api === 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 : [],
89
- context: surfaceContext,
90
- isRecommendedItem: isRecommendedItem,
91
- maxRecommendedItems: maxRecommendedItems
92
- })
93
- };
94
- }
95
- return snapshot.items;
96
- };
97
- return {
98
- getSnapshot: getSnapshot
71
+ return function (_ref4) {
72
+ var components = _ref4.components,
73
+ surfaceContext = _ref4.surfaceContext;
74
+ return surfaceContext ? getRecommendedComponents({
75
+ components: components,
76
+ context: surfaceContext,
77
+ isRecommendedItem: isRecommendedItem,
78
+ maxRecommendedItems: maxRecommendedItems
79
+ }) : [];
99
80
  };
100
81
  };
@@ -1,7 +1,7 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
3
  import _toArray from "@babel/runtime/helpers/toArray";
4
- var _excluded = ["rows", "selectableItems", "selectedItemIndex", "activeItemKey"];
4
+ var _excluded = ["rows", "selectableItems", "selectedItemIndex", "activeItemKey", "selectionSource"];
5
5
  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; }
6
6
  import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
7
7
  import { useIntl } from 'react-intl';
@@ -29,7 +29,8 @@ var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) {
29
29
  var _surfaceContext$get, _registeredMenu$maxHe;
30
30
  var emptyStateHandler = _ref.emptyStateHandler,
31
31
  fireAnalyticsEvent = _ref.fireAnalyticsEvent,
32
- getItemRank = _ref.getItemRank;
32
+ getItemRank = _ref.getItemRank,
33
+ getRecommendedItems = _ref.getRecommendedItems;
33
34
  var registeredMenu = useRegisteredMenuContext();
34
35
  var _registeredMenu$query = registeredMenu.query,
35
36
  query = _registeredMenu$query === void 0 ? '' : _registeredMenu$query,
@@ -49,6 +50,7 @@ var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) {
49
50
  components: components,
50
51
  formatMessage: formatMessage,
51
52
  getItemRank: runtimeItemRank !== null && runtimeItemRank !== void 0 ? runtimeItemRank : getItemRank,
53
+ getRecommendedItems: getRecommendedItems,
52
54
  query: query,
53
55
  rootComponent: rootComponent,
54
56
  selectCategoryItems: components.some(function (_ref2) {
@@ -57,7 +59,7 @@ var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) {
57
59
  }) ? selectQuickInsertCategoryItems : undefined,
58
60
  surfaceContext: surfaceContext
59
61
  });
60
- }, [components, formatMessage, getItemRank, query, rootComponent, runtimeItemRank, surfaceContext]);
62
+ }, [components, formatMessage, getItemRank, getRecommendedItems, query, rootComponent, runtimeItemRank, surfaceContext]);
61
63
  var resultCount = useMemo(function () {
62
64
  return model.sections.reduce(function (count, _ref3) {
63
65
  var _ref4 = _toArray(_ref3),
@@ -101,6 +103,7 @@ var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) {
101
103
  selectableItems = _useRegisteredMenu.selectableItems,
102
104
  selectedItemIndex = _useRegisteredMenu.selectedItemIndex,
103
105
  activeItemKey = _useRegisteredMenu.activeItemKey,
106
+ selectionSource = _useRegisteredMenu.selectionSource,
104
107
  listEvents = _objectWithoutProperties(_useRegisteredMenu, _excluded);
105
108
  var listId = useId();
106
109
  var _useState = useState({
@@ -187,7 +190,8 @@ var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) {
187
190
  onRenderedItemsChange: setRenderedItems,
188
191
  query: query,
189
192
  rows: rows,
190
- selectedItemIndex: selectedItemIndex
193
+ selectedItemIndex: selectedItemIndex,
194
+ selectionSource: selectionSource
191
195
  }) : /*#__PURE__*/React.createElement(ToolbarQuickInsertMenu, {
192
196
  Item: RegisteredQuickInsertMenuItem,
193
197
  activePreviewItemKey: activeItemKey,
@@ -205,7 +209,8 @@ var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) {
205
209
  onRenderedItemsChange: setRenderedItems,
206
210
  query: query,
207
211
  rows: rows,
208
- selectedItemIndex: selectedItemIndex
212
+ selectedItemIndex: selectedItemIndex,
213
+ selectionSource: selectionSource
209
214
  }))));
210
215
  };
211
216
  export default QuickInsertMenuRoot;
@@ -2,7 +2,6 @@ import React, { useMemo } from 'react';
2
2
  import { QuickInsertProvider } from '@atlaskit/editor-common/quick-insert/provider';
3
3
  import { useQuickInsertContext } from '@atlaskit/editor-common/quick-insert/use-quick-insert-context';
4
4
  export var RegisteredQuickInsertMenuItem = function RegisteredQuickInsertMenuItem(_ref) {
5
- var _registration$compone;
6
5
  var id = _ref.id,
7
6
  isSelected = _ref.isSelected,
8
7
  isActive = _ref.isActive,
@@ -27,8 +26,11 @@ export var RegisteredQuickInsertMenuItem = function RegisteredQuickInsertMenuIte
27
26
  surfaceContext: surfaceContext
28
27
  };
29
28
  }, [editorView, isOffline, popupsMountPoint, select, surfaceContext, isActive, id, isSelected]);
30
- var Component = (_registration$compone = registration.component) !== null && _registration$compone !== void 0 ? _registration$compone : React.Fragment;
29
+ var 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 var ToolbarQuickInsertMenu = function ToolbarQuickInsertMenu(_ref) {
32
32
  onItemVisibilityChange = _ref.onItemVisibilityChange,
33
33
  onRenderedItemsChange = _ref.onRenderedItemsChange,
34
34
  query = _ref.query,
35
- selectedItemIndex = _ref.selectedItemIndex;
35
+ selectedItemIndex = _ref.selectedItemIndex,
36
+ selectionSource = _ref.selectionSource;
36
37
  var footerItemIndex = itemCount - 1;
37
38
  var footerItemId = getQuickInsertMenuItemId(listId, footerItemIndex);
38
39
  var isEmptySearch = query !== '' && model.sections.length === 0;
@@ -83,6 +84,7 @@ export var ToolbarQuickInsertMenu = function ToolbarQuickInsertMenu(_ref) {
83
84
  getItemId: getItemId,
84
85
  activeItemKey: activePreviewItemKey,
85
86
  selectedItemIndex: selectedItemIndex,
87
+ selectionSource: selectionSource,
86
88
  scrollResetKey: query,
87
89
  onItemHover: onItemHover,
88
90
  onItemFocus: onItemFocus,
@@ -30,6 +30,7 @@ export var TypeAheadQuickInsertMenu = function TypeAheadQuickInsertMenu(_ref) {
30
30
  _ref$query = _ref.query,
31
31
  query = _ref$query === void 0 ? '' : _ref$query,
32
32
  selectedItemIndex = _ref.selectedItemIndex,
33
+ selectionSource = _ref.selectionSource,
33
34
  _ref$hasScrollPadding = _ref.hasScrollPadding,
34
35
  hasScrollPadding = _ref$hasScrollPadding === void 0 ? false : _ref$hasScrollPadding;
35
36
  var footerItemIndex = itemCount - 1;
@@ -57,6 +58,7 @@ export var TypeAheadQuickInsertMenu = function TypeAheadQuickInsertMenu(_ref) {
57
58
  getItemId: getItemId,
58
59
  activeItemKey: activeItemKey,
59
60
  selectedItemIndex: selectedItemIndex,
61
+ selectionSource: selectionSource,
60
62
  scrollResetKey: query,
61
63
  hasScrollPadding: hasScrollPadding,
62
64
  scrollTo: "top-on-reset",