@atlaskit/editor-plugin-type-ahead 12.0.6 → 12.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @atlaskit/editor-plugin-type-ahead
2
2
 
3
+ ## 12.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`dbf22f118dd9e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/dbf22f118dd9e) -
8
+ Rewrite Rovo Chat @-mention provider on a single Relay-native RovoChatMentionResource that fires
9
+ people + agents in parallel via Promise. People render as soon as URS resolves and agents pop in
10
+ below when ready. New aliased agentStudio_getAgents query consolidates 3 prefetch round trips into
11
+ 1, drops over-fetched fields, and uses real abort plumbing. Adds opt-in subscribeToItemsUpdates
12
+ multi-emit contract to the editor mention typeahead so progressive emissions are no longer dropped
13
+ after the first frame.
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+
19
+ ## 12.0.7
20
+
21
+ ### Patch Changes
22
+
23
+ - [`cf7797df5ff1e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cf7797df5ff1e) -
24
+ [ux] Add a Labs lozenge to the agent mention typeahead section.
25
+ - Updated dependencies
26
+
3
27
  ## 12.0.6
4
28
 
5
29
  ### Patch Changes
@@ -377,6 +377,7 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref4) {
377
377
  });
378
378
  }, [items]);
379
379
  var config = triggerHandler === null || triggerHandler === void 0 || (_triggerHandler$getMo = triggerHandler.getMoreOptionsButtonConfig) === null || _triggerHandler$getMo === void 0 ? void 0 : _triggerHandler$getMo.call(triggerHandler, intl);
380
+ var shouldRenderSectionLozenge = (0, _expVal.expVal)('platform_editor_agent_mentions', 'isEnabled', false);
380
381
  var handleClick = function handleClick() {
381
382
  if (onMoreOptionsClicked) {
382
383
  onMoreOptionsClicked();
@@ -401,6 +402,7 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref4) {
401
402
  if (!currentRow) {
402
403
  return null;
403
404
  }
405
+ var sectionLozenge = currentRow.type === 'section' && shouldRenderSectionLozenge ? currentRow.section.lozenge : null;
404
406
  return (0, _react2.jsx)(_CellMeasurer.CellMeasurer, {
405
407
  key: key,
406
408
  cache: cache,
@@ -425,11 +427,20 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref4) {
425
427
  }, currentRow.type === 'section' ? (0, _react2.jsx)(_compiled.Box, {
426
428
  paddingInline: "space.150",
427
429
  paddingBlock: "space.050"
430
+ }, sectionLozenge ? (0, _react2.jsx)(_compiled.Inline, {
431
+ as: "span",
432
+ space: "space.075",
433
+ alignBlock: "center"
428
434
  }, (0, _react2.jsx)(_compiled.Text, {
429
435
  as: "span",
430
436
  size: "small",
431
437
  color: "color.text.subtle",
432
438
  weight: "medium"
439
+ }, currentRow.section.title), sectionLozenge) : (0, _react2.jsx)(_compiled.Text, {
440
+ as: "span",
441
+ size: "small",
442
+ color: "color.text.subtle",
443
+ weight: "medium"
433
444
  }, currentRow.section.title)) : (0, _react2.jsx)(_TypeAheadListItem.TypeAheadListItem, {
434
445
  key: items[currentRow.itemIndex].title,
435
446
  item: items[currentRow.itemIndex],
@@ -111,6 +111,9 @@ var buildSectionedResult = exports.buildSectionedResult = function buildSectione
111
111
  startIndex: startIndex,
112
112
  title: _section.title
113
113
  };
114
+ if (_section.lozenge !== undefined) {
115
+ resolvedSection.lozenge = _section.lozenge;
116
+ }
114
117
  if (_section.sectionTitleDisplay) {
115
118
  resolvedSection.sectionTitleDisplay = _section.sectionTitleDisplay;
116
119
  }
@@ -21,14 +21,15 @@ var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler,
21
21
  setItems = _useState2[1];
22
22
  var componentIsMounted = (0, _react.useRef)(true);
23
23
  var editorViewRef = (0, _react.useRef)(editorView);
24
+ var latestQueryRef = (0, _react.useRef)(query);
25
+ latestQueryRef.current = query;
24
26
  (0, _react.useEffect)(function () {
25
- var getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
26
- if (!getItems) {
27
- setItems(EMPTY_LIST_ITEM);
28
- return;
29
- }
27
+ var requestQuery = query;
28
+ var isStaleRequest = function isStaleRequest() {
29
+ return latestQueryRef.current !== requestQuery;
30
+ };
30
31
  var options = {
31
- query: query || '',
32
+ query: requestQuery || '',
32
33
  editorState: editorView.state
33
34
  };
34
35
  var view = editorViewRef.current;
@@ -38,10 +39,19 @@ var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler,
38
39
  api === null || api === void 0 || api.core.actions.execute((0, _clearListError.clearListError)());
39
40
  });
40
41
  }
41
- getItems(options).then(function (result) {
42
+
43
+ /**
44
+ * Shared render pipeline used by both the single-shot `getItems`
45
+ * Promise path and the opt-in multi-emit `subscribeToItemsUpdates`
46
+ * path. Renders the dropdown with whatever items it is given.
47
+ *
48
+ * Both paths share the empty-state injection, section-building
49
+ * and "View more" placeholder logic — extracting this helper
50
+ * avoids any chance the two paths drift in subtle rendering
51
+ * behaviour.
52
+ */
53
+ var renderResult = function renderResult(result) {
42
54
  var _triggerHandler$getEm;
43
- // Inject empty list item here so it flows through the normal list rendering and keyboard
44
- // navigation paths
45
55
  var emptyItem = result.length === 0 && (0, _expValEquals.expValEquals)('platform_editor_insert_menu_ai', 'isEnabled', true) ? (_triggerHandler$getEm = triggerHandler.getEmptyItem) === null || _triggerHandler$getEm === void 0 ? void 0 : _triggerHandler$getEm.call(triggerHandler, {
46
56
  editorState: editorView.state
47
57
  }) : undefined;
@@ -56,15 +66,18 @@ var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler,
56
66
  if (componentIsMounted.current) {
57
67
  setItems(list);
58
68
  }
59
-
60
- // Add a placeholder item for view more button so that it can be traversed with arrow keys
61
69
  var viewMoreItem = {
62
70
  title: 'View more'
63
71
  };
64
72
  queueMicrotask(function () {
65
73
  (0, _updateListItems.updateListItem)(showViewMore ? list.concat(viewMoreItem) : list, sections)(view.state, view.dispatch);
66
74
  });
67
- }).catch(function (e) {
75
+ };
76
+
77
+ // Matches the pre-refactor implicit-any contract for the original
78
+ // `.catch((e) => updateListError(e)(...))` path.
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
+ var handleError = function handleError(e) {
68
81
  if ((0, _experiments.editorExperiment)('platform_editor_offline_editing_web', true)) {
69
82
  if (e) {
70
83
  if (componentIsMounted.current) {
@@ -75,7 +88,42 @@ var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler,
75
88
  });
76
89
  }
77
90
  }
78
- });
91
+ };
92
+
93
+ // Multi-emit path: handler opts in by implementing
94
+ // `subscribeToItemsUpdates`. The handler controls when to push
95
+ // updates; we re-render on every push for the lifetime of this
96
+ // effect.
97
+ var subscribeToItemsUpdates = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.subscribeToItemsUpdates;
98
+ if (subscribeToItemsUpdates) {
99
+ var stale = false;
100
+ var _subscribeToItemsUpda = subscribeToItemsUpdates(options),
101
+ initial = _subscribeToItemsUpda.initial,
102
+ subscribe = _subscribeToItemsUpda.subscribe;
103
+ initial.then(function (result) {
104
+ if (!stale && !isStaleRequest()) {
105
+ renderResult(result);
106
+ }
107
+ }).catch(handleError);
108
+ var unsubscribe = subscribe(function (items) {
109
+ if (stale || isStaleRequest() || !componentIsMounted.current) {
110
+ return;
111
+ }
112
+ renderResult(items);
113
+ });
114
+ return function () {
115
+ stale = true;
116
+ unsubscribe();
117
+ };
118
+ }
119
+
120
+ // Existing single-shot path. Unchanged in behaviour.
121
+ var getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
122
+ if (!getItems) {
123
+ setItems(EMPTY_LIST_ITEM);
124
+ return;
125
+ }
126
+ getItems(options).then(renderResult).catch(handleError);
79
127
 
80
128
  // ignore because EditorView is mutable but we don't want to
81
129
  // call loadItems when it changes, only when the query changes
@@ -15,7 +15,7 @@ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/
15
15
  import { SelectItemMode, typeAheadListMessages } from '@atlaskit/editor-common/type-ahead';
16
16
  import { AssistiveText } from '@atlaskit/editor-common/ui';
17
17
  import { MenuGroup } from '@atlaskit/menu';
18
- import { Text, Box } from '@atlaskit/primitives/compiled';
18
+ import { Box, Inline, Text } from '@atlaskit/primitives/compiled';
19
19
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
20
20
  import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
21
21
  import { closeTypeAhead } from '../pm-plugins/commands/close-type-ahead';
@@ -350,6 +350,7 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
350
350
  return items.findIndex(item => item.isDisabledOffline !== true);
351
351
  }, [items]);
352
352
  const config = triggerHandler === null || triggerHandler === void 0 ? void 0 : (_triggerHandler$getMo = triggerHandler.getMoreOptionsButtonConfig) === null || _triggerHandler$getMo === void 0 ? void 0 : _triggerHandler$getMo.call(triggerHandler, intl);
353
+ const shouldRenderSectionLozenge = expVal('platform_editor_agent_mentions', 'isEnabled', false);
353
354
  const handleClick = () => {
354
355
  if (onMoreOptionsClicked) {
355
356
  onMoreOptionsClicked();
@@ -376,6 +377,7 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
376
377
  if (!currentRow) {
377
378
  return null;
378
379
  }
380
+ const sectionLozenge = currentRow.type === 'section' && shouldRenderSectionLozenge ? currentRow.section.lozenge : null;
379
381
  return jsx(CellMeasurer, {
380
382
  key: key,
381
383
  cache: cache,
@@ -398,11 +400,20 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
398
400
  }, currentRow.type === 'section' ? jsx(Box, {
399
401
  paddingInline: "space.150",
400
402
  paddingBlock: "space.050"
403
+ }, sectionLozenge ? jsx(Inline, {
404
+ as: "span",
405
+ space: "space.075",
406
+ alignBlock: "center"
401
407
  }, jsx(Text, {
402
408
  as: "span",
403
409
  size: "small",
404
410
  color: "color.text.subtle",
405
411
  weight: "medium"
412
+ }, currentRow.section.title), sectionLozenge) : jsx(Text, {
413
+ as: "span",
414
+ size: "small",
415
+ color: "color.text.subtle",
416
+ weight: "medium"
406
417
  }, currentRow.section.title)) : jsx(TypeAheadListItem, {
407
418
  key: items[currentRow.itemIndex].title,
408
419
  item: items[currentRow.itemIndex],
@@ -68,6 +68,9 @@ export const buildSectionedResult = ({
68
68
  startIndex,
69
69
  title: section.title
70
70
  };
71
+ if (section.lozenge !== undefined) {
72
+ resolvedSection.lozenge = section.lozenge;
73
+ }
71
74
  if (section.sectionTitleDisplay) {
72
75
  resolvedSection.sectionTitleDisplay = section.sectionTitleDisplay;
73
76
  }
@@ -10,14 +10,13 @@ export const useLoadItems = (triggerHandler, editorView, query, showViewMore, ap
10
10
  const [items, setItems] = useState(EMPTY_LIST_ITEM);
11
11
  const componentIsMounted = useRef(true);
12
12
  const editorViewRef = useRef(editorView);
13
+ const latestQueryRef = useRef(query);
14
+ latestQueryRef.current = query;
13
15
  useEffect(() => {
14
- const getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
15
- if (!getItems) {
16
- setItems(EMPTY_LIST_ITEM);
17
- return;
18
- }
16
+ const requestQuery = query;
17
+ const isStaleRequest = () => latestQueryRef.current !== requestQuery;
19
18
  const options = {
20
- query: query || '',
19
+ query: requestQuery || '',
21
20
  editorState: editorView.state
22
21
  };
23
22
  const {
@@ -29,10 +28,19 @@ export const useLoadItems = (triggerHandler, editorView, query, showViewMore, ap
29
28
  api === null || api === void 0 ? void 0 : api.core.actions.execute(clearListError());
30
29
  });
31
30
  }
32
- getItems(options).then(result => {
31
+
32
+ /**
33
+ * Shared render pipeline used by both the single-shot `getItems`
34
+ * Promise path and the opt-in multi-emit `subscribeToItemsUpdates`
35
+ * path. Renders the dropdown with whatever items it is given.
36
+ *
37
+ * Both paths share the empty-state injection, section-building
38
+ * and "View more" placeholder logic — extracting this helper
39
+ * avoids any chance the two paths drift in subtle rendering
40
+ * behaviour.
41
+ */
42
+ const renderResult = result => {
33
43
  var _triggerHandler$getEm;
34
- // Inject empty list item here so it flows through the normal list rendering and keyboard
35
- // navigation paths
36
44
  const emptyItem = result.length === 0 && expValEquals('platform_editor_insert_menu_ai', 'isEnabled', true) ? (_triggerHandler$getEm = triggerHandler.getEmptyItem) === null || _triggerHandler$getEm === void 0 ? void 0 : _triggerHandler$getEm.call(triggerHandler, {
37
45
  editorState: editorView.state
38
46
  }) : undefined;
@@ -48,15 +56,18 @@ export const useLoadItems = (triggerHandler, editorView, query, showViewMore, ap
48
56
  if (componentIsMounted.current) {
49
57
  setItems(list);
50
58
  }
51
-
52
- // Add a placeholder item for view more button so that it can be traversed with arrow keys
53
59
  const viewMoreItem = {
54
60
  title: 'View more'
55
61
  };
56
62
  queueMicrotask(() => {
57
63
  updateListItem(showViewMore ? list.concat(viewMoreItem) : list, sections)(view.state, view.dispatch);
58
64
  });
59
- }).catch(e => {
65
+ };
66
+
67
+ // Matches the pre-refactor implicit-any contract for the original
68
+ // `.catch((e) => updateListError(e)(...))` path.
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ const handleError = e => {
60
71
  if (editorExperiment('platform_editor_offline_editing_web', true)) {
61
72
  if (e) {
62
73
  if (componentIsMounted.current) {
@@ -67,7 +78,43 @@ export const useLoadItems = (triggerHandler, editorView, query, showViewMore, ap
67
78
  });
68
79
  }
69
80
  }
70
- });
81
+ };
82
+
83
+ // Multi-emit path: handler opts in by implementing
84
+ // `subscribeToItemsUpdates`. The handler controls when to push
85
+ // updates; we re-render on every push for the lifetime of this
86
+ // effect.
87
+ const subscribeToItemsUpdates = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.subscribeToItemsUpdates;
88
+ if (subscribeToItemsUpdates) {
89
+ let stale = false;
90
+ const {
91
+ initial,
92
+ subscribe
93
+ } = subscribeToItemsUpdates(options);
94
+ initial.then(result => {
95
+ if (!stale && !isStaleRequest()) {
96
+ renderResult(result);
97
+ }
98
+ }).catch(handleError);
99
+ const unsubscribe = subscribe(items => {
100
+ if (stale || isStaleRequest() || !componentIsMounted.current) {
101
+ return;
102
+ }
103
+ renderResult(items);
104
+ });
105
+ return () => {
106
+ stale = true;
107
+ unsubscribe();
108
+ };
109
+ }
110
+
111
+ // Existing single-shot path. Unchanged in behaviour.
112
+ const getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
113
+ if (!getItems) {
114
+ setItems(EMPTY_LIST_ITEM);
115
+ return;
116
+ }
117
+ getItems(options).then(renderResult).catch(handleError);
71
118
 
72
119
  // ignore because EditorView is mutable but we don't want to
73
120
  // call loadItems when it changes, only when the query changes
@@ -17,7 +17,7 @@ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/
17
17
  import { SelectItemMode, typeAheadListMessages } from '@atlaskit/editor-common/type-ahead';
18
18
  import { AssistiveText } from '@atlaskit/editor-common/ui';
19
19
  import { MenuGroup } from '@atlaskit/menu';
20
- import { Text, Box } from '@atlaskit/primitives/compiled';
20
+ import { Box, Inline, Text } from '@atlaskit/primitives/compiled';
21
21
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
22
22
  import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
23
23
  import { closeTypeAhead } from '../pm-plugins/commands/close-type-ahead';
@@ -368,6 +368,7 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref4) {
368
368
  });
369
369
  }, [items]);
370
370
  var config = triggerHandler === null || triggerHandler === void 0 || (_triggerHandler$getMo = triggerHandler.getMoreOptionsButtonConfig) === null || _triggerHandler$getMo === void 0 ? void 0 : _triggerHandler$getMo.call(triggerHandler, intl);
371
+ var shouldRenderSectionLozenge = expVal('platform_editor_agent_mentions', 'isEnabled', false);
371
372
  var handleClick = function handleClick() {
372
373
  if (onMoreOptionsClicked) {
373
374
  onMoreOptionsClicked();
@@ -392,6 +393,7 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref4) {
392
393
  if (!currentRow) {
393
394
  return null;
394
395
  }
396
+ var sectionLozenge = currentRow.type === 'section' && shouldRenderSectionLozenge ? currentRow.section.lozenge : null;
395
397
  return jsx(CellMeasurer, {
396
398
  key: key,
397
399
  cache: cache,
@@ -416,11 +418,20 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref4) {
416
418
  }, currentRow.type === 'section' ? jsx(Box, {
417
419
  paddingInline: "space.150",
418
420
  paddingBlock: "space.050"
421
+ }, sectionLozenge ? jsx(Inline, {
422
+ as: "span",
423
+ space: "space.075",
424
+ alignBlock: "center"
419
425
  }, jsx(Text, {
420
426
  as: "span",
421
427
  size: "small",
422
428
  color: "color.text.subtle",
423
429
  weight: "medium"
430
+ }, currentRow.section.title), sectionLozenge) : jsx(Text, {
431
+ as: "span",
432
+ size: "small",
433
+ color: "color.text.subtle",
434
+ weight: "medium"
424
435
  }, currentRow.section.title)) : jsx(TypeAheadListItem, {
425
436
  key: items[currentRow.itemIndex].title,
426
437
  item: items[currentRow.itemIndex],
@@ -104,6 +104,9 @@ export var buildSectionedResult = function buildSectionedResult(_ref) {
104
104
  startIndex: startIndex,
105
105
  title: _section.title
106
106
  };
107
+ if (_section.lozenge !== undefined) {
108
+ resolvedSection.lozenge = _section.lozenge;
109
+ }
107
110
  if (_section.sectionTitleDisplay) {
108
111
  resolvedSection.sectionTitleDisplay = _section.sectionTitleDisplay;
109
112
  }
@@ -14,14 +14,15 @@ export var useLoadItems = function useLoadItems(triggerHandler, editorView, quer
14
14
  setItems = _useState2[1];
15
15
  var componentIsMounted = useRef(true);
16
16
  var editorViewRef = useRef(editorView);
17
+ var latestQueryRef = useRef(query);
18
+ latestQueryRef.current = query;
17
19
  useEffect(function () {
18
- var getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
19
- if (!getItems) {
20
- setItems(EMPTY_LIST_ITEM);
21
- return;
22
- }
20
+ var requestQuery = query;
21
+ var isStaleRequest = function isStaleRequest() {
22
+ return latestQueryRef.current !== requestQuery;
23
+ };
23
24
  var options = {
24
- query: query || '',
25
+ query: requestQuery || '',
25
26
  editorState: editorView.state
26
27
  };
27
28
  var view = editorViewRef.current;
@@ -31,10 +32,19 @@ export var useLoadItems = function useLoadItems(triggerHandler, editorView, quer
31
32
  api === null || api === void 0 || api.core.actions.execute(clearListError());
32
33
  });
33
34
  }
34
- getItems(options).then(function (result) {
35
+
36
+ /**
37
+ * Shared render pipeline used by both the single-shot `getItems`
38
+ * Promise path and the opt-in multi-emit `subscribeToItemsUpdates`
39
+ * path. Renders the dropdown with whatever items it is given.
40
+ *
41
+ * Both paths share the empty-state injection, section-building
42
+ * and "View more" placeholder logic — extracting this helper
43
+ * avoids any chance the two paths drift in subtle rendering
44
+ * behaviour.
45
+ */
46
+ var renderResult = function renderResult(result) {
35
47
  var _triggerHandler$getEm;
36
- // Inject empty list item here so it flows through the normal list rendering and keyboard
37
- // navigation paths
38
48
  var emptyItem = result.length === 0 && expValEquals('platform_editor_insert_menu_ai', 'isEnabled', true) ? (_triggerHandler$getEm = triggerHandler.getEmptyItem) === null || _triggerHandler$getEm === void 0 ? void 0 : _triggerHandler$getEm.call(triggerHandler, {
39
49
  editorState: editorView.state
40
50
  }) : undefined;
@@ -49,15 +59,18 @@ export var useLoadItems = function useLoadItems(triggerHandler, editorView, quer
49
59
  if (componentIsMounted.current) {
50
60
  setItems(list);
51
61
  }
52
-
53
- // Add a placeholder item for view more button so that it can be traversed with arrow keys
54
62
  var viewMoreItem = {
55
63
  title: 'View more'
56
64
  };
57
65
  queueMicrotask(function () {
58
66
  updateListItem(showViewMore ? list.concat(viewMoreItem) : list, sections)(view.state, view.dispatch);
59
67
  });
60
- }).catch(function (e) {
68
+ };
69
+
70
+ // Matches the pre-refactor implicit-any contract for the original
71
+ // `.catch((e) => updateListError(e)(...))` path.
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ var handleError = function handleError(e) {
61
74
  if (editorExperiment('platform_editor_offline_editing_web', true)) {
62
75
  if (e) {
63
76
  if (componentIsMounted.current) {
@@ -68,7 +81,42 @@ export var useLoadItems = function useLoadItems(triggerHandler, editorView, quer
68
81
  });
69
82
  }
70
83
  }
71
- });
84
+ };
85
+
86
+ // Multi-emit path: handler opts in by implementing
87
+ // `subscribeToItemsUpdates`. The handler controls when to push
88
+ // updates; we re-render on every push for the lifetime of this
89
+ // effect.
90
+ var subscribeToItemsUpdates = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.subscribeToItemsUpdates;
91
+ if (subscribeToItemsUpdates) {
92
+ var stale = false;
93
+ var _subscribeToItemsUpda = subscribeToItemsUpdates(options),
94
+ initial = _subscribeToItemsUpda.initial,
95
+ subscribe = _subscribeToItemsUpda.subscribe;
96
+ initial.then(function (result) {
97
+ if (!stale && !isStaleRequest()) {
98
+ renderResult(result);
99
+ }
100
+ }).catch(handleError);
101
+ var unsubscribe = subscribe(function (items) {
102
+ if (stale || isStaleRequest() || !componentIsMounted.current) {
103
+ return;
104
+ }
105
+ renderResult(items);
106
+ });
107
+ return function () {
108
+ stale = true;
109
+ unsubscribe();
110
+ };
111
+ }
112
+
113
+ // Existing single-shot path. Unchanged in behaviour.
114
+ var getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
115
+ if (!getItems) {
116
+ setItems(EMPTY_LIST_ITEM);
117
+ return;
118
+ }
119
+ getItems(options).then(renderResult).catch(handleError);
72
120
 
73
121
  // ignore because EditorView is mutable but we don't want to
74
122
  // call loadItems when it changes, only when the query changes
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from 'react';
1
2
  import type { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
3
  import type { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
3
4
  import type { TypeAheadHandler, TypeAheadItem, TypeAheadStats, UiComponentFactoryParams } from '@atlaskit/editor-common/types';
@@ -47,6 +48,7 @@ export type TypeAheadPluginState = {
47
48
  export type TypeAheadResolvedSection = {
48
49
  endIndex: number;
49
50
  id: string;
51
+ lozenge?: ReactNode;
50
52
  /**
51
53
  * Section title display rules copied from the section definition and optional runtime updates.
52
54
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-type-ahead",
3
- "version": "12.0.6",
3
+ "version": "12.1.0",
4
4
  "description": "Type-ahead plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -36,8 +36,8 @@
36
36
  "@atlaskit/primitives": "^20.0.0",
37
37
  "@atlaskit/prosemirror-history": "^1.0.0",
38
38
  "@atlaskit/prosemirror-input-rules": "^4.0.0",
39
- "@atlaskit/tmp-editor-statsig": "^109.0.0",
40
- "@atlaskit/tokens": "^14.0.0",
39
+ "@atlaskit/tmp-editor-statsig": "^110.0.0",
40
+ "@atlaskit/tokens": "^15.0.0",
41
41
  "@atlaskit/visually-hidden": "^4.0.0",
42
42
  "@babel/runtime": "^7.0.0",
43
43
  "@emotion/react": "^11.7.1",
@@ -48,7 +48,7 @@
48
48
  "w3c-keyname": "^2.1.8"
49
49
  },
50
50
  "peerDependencies": {
51
- "@atlaskit/editor-common": "^116.6.0",
51
+ "@atlaskit/editor-common": "^116.11.0",
52
52
  "react": "^18.2.0",
53
53
  "react-dom": "^18.2.0",
54
54
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
@@ -58,7 +58,7 @@
58
58
  "@types/react-virtualized": "^9.18.12",
59
59
  "react": "^18.2.0",
60
60
  "react-dom": "^18.2.0",
61
- "react-intl": "^6.6.2",
61
+ "react-intl": "^7.0.0",
62
62
  "wait-for-expect": "^1.2.0"
63
63
  },
64
64
  "techstack": {