@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 +24 -0
- package/dist/cjs/ui/TypeAheadList.js +11 -0
- package/dist/cjs/ui/hooks/build-sectioned-result.js +3 -0
- package/dist/cjs/ui/hooks/use-load-items.js +61 -13
- package/dist/es2019/ui/TypeAheadList.js +12 -1
- package/dist/es2019/ui/hooks/build-sectioned-result.js +3 -0
- package/dist/es2019/ui/hooks/use-load-items.js +60 -13
- package/dist/esm/ui/TypeAheadList.js +12 -1
- package/dist/esm/ui/hooks/build-sectioned-result.js +3 -0
- package/dist/esm/ui/hooks/use-load-items.js +61 -13
- package/dist/types/types/index.d.ts +2 -0
- package/package.json +5 -5
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
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
27
|
+
var requestQuery = query;
|
|
28
|
+
var isStaleRequest = function isStaleRequest() {
|
|
29
|
+
return latestQueryRef.current !== requestQuery;
|
|
30
|
+
};
|
|
30
31
|
var options = {
|
|
31
|
-
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
|
-
|
|
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
|
-
}
|
|
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 {
|
|
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
|
|
15
|
-
|
|
16
|
-
setItems(EMPTY_LIST_ITEM);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
16
|
+
const requestQuery = query;
|
|
17
|
+
const isStaleRequest = () => latestQueryRef.current !== requestQuery;
|
|
19
18
|
const options = {
|
|
20
|
-
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
|
-
|
|
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
|
-
}
|
|
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 {
|
|
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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
20
|
+
var requestQuery = query;
|
|
21
|
+
var isStaleRequest = function isStaleRequest() {
|
|
22
|
+
return latestQueryRef.current !== requestQuery;
|
|
23
|
+
};
|
|
23
24
|
var options = {
|
|
24
|
-
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
|
-
|
|
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
|
-
}
|
|
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
|
|
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": "^
|
|
40
|
-
"@atlaskit/tokens": "^
|
|
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.
|
|
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": "^
|
|
61
|
+
"react-intl": "^7.0.0",
|
|
62
62
|
"wait-for-expect": "^1.2.0"
|
|
63
63
|
},
|
|
64
64
|
"techstack": {
|