@atlaskit/editor-plugin-type-ahead 2.1.1 → 2.1.2
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 +12 -0
- package/dist/cjs/ui/TypeAheadList.js +32 -14
- package/dist/cjs/ui/TypeAheadPopup.js +24 -17
- package/dist/cjs/ui/ViewMore.js +49 -7
- package/dist/cjs/ui/WrapperTypeAhead.js +5 -1
- package/dist/cjs/ui/hooks/use-load-items.js +5 -2
- package/dist/cjs/ui/modern/TypeAheadPopup.js +22 -13
- package/dist/es2019/ui/TypeAheadList.js +32 -14
- package/dist/es2019/ui/TypeAheadPopup.js +24 -17
- package/dist/es2019/ui/ViewMore.js +45 -1
- package/dist/es2019/ui/WrapperTypeAhead.js +6 -2
- package/dist/es2019/ui/hooks/use-load-items.js +5 -2
- package/dist/es2019/ui/modern/TypeAheadPopup.js +22 -13
- package/dist/esm/ui/TypeAheadList.js +32 -14
- package/dist/esm/ui/TypeAheadPopup.js +24 -17
- package/dist/esm/ui/ViewMore.js +43 -1
- package/dist/esm/ui/WrapperTypeAhead.js +6 -2
- package/dist/esm/ui/hooks/use-load-items.js +5 -2
- package/dist/esm/ui/modern/TypeAheadPopup.js +22 -13
- package/dist/types/ui/TypeAheadList.d.ts +2 -0
- package/dist/types/ui/ViewMore.d.ts +3 -6
- package/dist/types/ui/hooks/use-load-items.d.ts +1 -1
- package/dist/types-ts4.5/ui/TypeAheadList.d.ts +2 -0
- package/dist/types-ts4.5/ui/ViewMore.d.ts +3 -6
- package/dist/types-ts4.5/ui/hooks/use-load-items.d.ts +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-type-ahead
|
|
2
2
|
|
|
3
|
+
## 2.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#122304](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/122304)
|
|
8
|
+
[`55aeeb7141654`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/55aeeb7141654) -
|
|
9
|
+
[HOT-115591] Fix emoji popup close when scrolling
|
|
10
|
+
- [#122337](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/122337)
|
|
11
|
+
[`2775fb4a3b7d6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2775fb4a3b7d6) -
|
|
12
|
+
[ux] [ED-26824] Add keyboard support (up/down to navigate, enter to insert) to view more button
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
3
15
|
## 2.1.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -21,6 +21,7 @@ var _constants = require("../pm-plugins/constants");
|
|
|
21
21
|
var _utils = require("../pm-plugins/utils");
|
|
22
22
|
var _AssistiveText = require("./AssistiveText");
|
|
23
23
|
var _TypeAheadListItem = require("./TypeAheadListItem");
|
|
24
|
+
var _ViewMore = require("./ViewMore");
|
|
24
25
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
25
26
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
26
27
|
/**
|
|
@@ -63,7 +64,8 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
63
64
|
triggerHandler = _ref2.triggerHandler,
|
|
64
65
|
moreElementsInQuickInsertViewEnabled = _ref2.moreElementsInQuickInsertViewEnabled,
|
|
65
66
|
api = _ref2.api,
|
|
66
|
-
showViewMore = _ref2.showViewMore
|
|
67
|
+
showViewMore = _ref2.showViewMore,
|
|
68
|
+
onViewMoreClick = _ref2.onViewMoreClick;
|
|
67
69
|
var listRef = (0, _react.useRef)();
|
|
68
70
|
var listContainerRef = (0, _react.useRef)(null);
|
|
69
71
|
var lastVisibleIndexes = (0, _react.useRef)({
|
|
@@ -72,7 +74,10 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
72
74
|
startIndex: 0,
|
|
73
75
|
stopIndex: 0
|
|
74
76
|
});
|
|
75
|
-
|
|
77
|
+
|
|
78
|
+
// Exclude view more item from the count
|
|
79
|
+
var itemsLength = showViewMore ? items.length - 1 : items.length;
|
|
80
|
+
var estimatedHeight = itemsLength * LIST_ITEM_ESTIMATED_HEIGHT;
|
|
76
81
|
var _useState = (0, _react.useState)(Math.min(estimatedHeight, fitHeight)),
|
|
77
82
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
78
83
|
height = _useState2[0],
|
|
@@ -138,7 +143,10 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
138
143
|
// to calculate each height. THen, we can schedule a new frame when this one finishs.
|
|
139
144
|
requestAnimationFrame(function () {
|
|
140
145
|
requestAnimationFrame(function () {
|
|
141
|
-
var
|
|
146
|
+
var isViewMoreSelected = showViewMore && selectedIndex === itemsLength;
|
|
147
|
+
var isSelectedItemVisible = selectedIndex >= lastVisibleStartIndex && selectedIndex <= lastVisibleStopIndex ||
|
|
148
|
+
// view more is always visible, hence no scrolling
|
|
149
|
+
isViewMoreSelected;
|
|
142
150
|
|
|
143
151
|
//Should scroll to the list item only when the selectedIndex >= 0 and item is not visible
|
|
144
152
|
if (!isSelectedItemVisible && selectedIndex !== -1) {
|
|
@@ -148,7 +156,7 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
148
156
|
}
|
|
149
157
|
});
|
|
150
158
|
});
|
|
151
|
-
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex]);
|
|
159
|
+
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex, itemsLength, showViewMore]);
|
|
152
160
|
var _onMouseMove = function onMouseMove(event, index) {
|
|
153
161
|
event.preventDefault();
|
|
154
162
|
event.stopPropagation();
|
|
@@ -161,7 +169,10 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
161
169
|
if (!listRef.current) {
|
|
162
170
|
return;
|
|
163
171
|
}
|
|
164
|
-
var
|
|
172
|
+
var isViewMoreSelected = showViewMore && selectedIndex === itemsLength;
|
|
173
|
+
var isSelectedItemVisible = selectedIndex >= lastVisibleStartIndex && selectedIndex <= lastVisibleStopIndex ||
|
|
174
|
+
// view more is always visible, hence no scrolling
|
|
175
|
+
isViewMoreSelected;
|
|
165
176
|
|
|
166
177
|
//Should scroll to the list item only when the selectedIndex >= 0 and item is not visible
|
|
167
178
|
if (!isSelectedItemVisible && selectedIndex !== -1) {
|
|
@@ -169,7 +180,7 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
169
180
|
} else if (selectedIndex === -1) {
|
|
170
181
|
listRef.current.scrollToRow(0);
|
|
171
182
|
}
|
|
172
|
-
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex]);
|
|
183
|
+
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex, itemsLength, showViewMore]);
|
|
173
184
|
(0, _react.useLayoutEffect)(function () {
|
|
174
185
|
setCache(new _CellMeasurer.CellMeasurerCache({
|
|
175
186
|
fixedWidth: true,
|
|
@@ -187,13 +198,15 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
187
198
|
});
|
|
188
199
|
}, [items]);
|
|
189
200
|
(0, _react.useLayoutEffect)(function () {
|
|
190
|
-
|
|
201
|
+
// Exclude view more item from the count
|
|
202
|
+
var itemsToRender = showViewMore ? items.slice(0, -1) : items;
|
|
203
|
+
var height = Math.min(itemsToRender.reduce(function (prevValue, currentValue, index) {
|
|
191
204
|
return prevValue + cache.rowHeight({
|
|
192
205
|
index: index
|
|
193
206
|
});
|
|
194
207
|
}, 0), fitHeight);
|
|
195
208
|
setHeight(height);
|
|
196
|
-
}, [items, cache, fitHeight]);
|
|
209
|
+
}, [items, cache, fitHeight, showViewMore]);
|
|
197
210
|
(0, _react.useLayoutEffect)(function () {
|
|
198
211
|
if (!listContainerRef.current) {
|
|
199
212
|
return;
|
|
@@ -246,7 +259,7 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
246
259
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
247
260
|
element === null || element === void 0 || element.removeEventListener('keydown', handleKeyDown);
|
|
248
261
|
};
|
|
249
|
-
}, [editorView.state, focusTargetElement, selectNextItem, selectPreviousItem, selectedIndex, onItemClick,
|
|
262
|
+
}, [editorView.state, focusTargetElement, selectNextItem, selectPreviousItem, selectedIndex, onItemClick, itemsLength]);
|
|
250
263
|
var firstOnlineSupportedRow = (0, _react.useMemo)(function () {
|
|
251
264
|
return items.findIndex(function (item) {
|
|
252
265
|
return item.isDisabledOffline !== true;
|
|
@@ -276,7 +289,7 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
276
289
|
key: items[index].title,
|
|
277
290
|
item: currentItem,
|
|
278
291
|
firstOnlineSupportedIndex: firstOnlineSupportedRow,
|
|
279
|
-
itemsLength:
|
|
292
|
+
itemsLength: itemsLength,
|
|
280
293
|
itemIndex: index,
|
|
281
294
|
selectedIndex: selectedIndex,
|
|
282
295
|
onItemClick: actions.onItemClick,
|
|
@@ -306,8 +319,10 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
306
319
|
})));
|
|
307
320
|
var ListContent = (0, _react2.jsx)(_List.List, {
|
|
308
321
|
rowRenderer: renderRow,
|
|
309
|
-
ref: listRef
|
|
310
|
-
|
|
322
|
+
ref: listRef
|
|
323
|
+
// Skip rendering the view more button in the list
|
|
324
|
+
,
|
|
325
|
+
rowCount: itemsLength,
|
|
311
326
|
rowHeight: cache.rowHeight,
|
|
312
327
|
onRowsRendered: onItemsRendered,
|
|
313
328
|
width: LIST_WIDTH,
|
|
@@ -341,8 +356,11 @@ var TypeAheadListComponent = /*#__PURE__*/_react.default.memo(function (_ref2) {
|
|
|
341
356
|
}, (0, _react2.jsx)("div", {
|
|
342
357
|
id: menuGroupId,
|
|
343
358
|
ref: listContainerRef
|
|
344
|
-
}, !showViewMore ||
|
|
345
|
-
|
|
359
|
+
}, !showViewMore || itemsLength ? ListContent : EmptyResultView, showViewMore && onViewMoreClick && (0, _react2.jsx)(_ViewMore.ViewMore, {
|
|
360
|
+
onClick: onViewMoreClick,
|
|
361
|
+
isFocused: selectedIndex === itemsLength
|
|
362
|
+
}), (0, _react2.jsx)(TypeaheadAssistiveTextPureComponent, {
|
|
363
|
+
numberOfResults: itemsLength.toString()
|
|
346
364
|
})));
|
|
347
365
|
});
|
|
348
366
|
var TypeAheadList = exports.TypeAheadList = (0, _reactIntlNext.injectIntl)(TypeAheadListComponent);
|
|
@@ -20,7 +20,6 @@ var _colors = require("@atlaskit/theme/colors");
|
|
|
20
20
|
var _constants = require("../pm-plugins/constants");
|
|
21
21
|
var _TypeAheadErrorFallback = require("./TypeAheadErrorFallback");
|
|
22
22
|
var _TypeAheadList = require("./TypeAheadList");
|
|
23
|
-
var _ViewMore = require("./ViewMore");
|
|
24
23
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
25
24
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
26
25
|
/**
|
|
@@ -220,22 +219,31 @@ var TypeAheadPopup = exports.TypeAheadPopup = /*#__PURE__*/_react.default.memo(f
|
|
|
220
219
|
var _window$getSelection2;
|
|
221
220
|
// Check if new focus point is inside the current editor. If it is not we
|
|
222
221
|
// want to close the typeahead popup regardless of text selection state
|
|
223
|
-
var
|
|
222
|
+
var currentFocus = (_window$getSelection2 = window.getSelection()) === null || _window$getSelection2 === void 0 ? void 0 : _window$getSelection2.focusNode; // the focusNode is either TextNode, ElementNode
|
|
223
|
+
// if currentFocus is not HTMLElement, take its parent node as focusNode
|
|
224
|
+
var focusNode = currentFocus instanceof HTMLElement ? currentFocus : currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.parentNode;
|
|
224
225
|
if (focusNode instanceof HTMLElement) {
|
|
225
226
|
var innerEditor = focusNode.closest('.extension-editable-area');
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
227
|
+
if (innerEditor) {
|
|
228
|
+
// When there is no related target, we default to not closing the popup
|
|
229
|
+
var newFocusInsideCurrentEditor = !relatedTarget;
|
|
230
|
+
if (relatedTarget instanceof HTMLElement) {
|
|
231
|
+
if (innerEditor) {
|
|
232
|
+
// check if the new focus is inside inner editor, keep popup opens
|
|
233
|
+
newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
|
|
234
|
+
} else {
|
|
235
|
+
// if the new focus contains current focus node, the popup won't close
|
|
236
|
+
newFocusInsideCurrentEditor = relatedTarget.contains(focusNode);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
// if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
|
|
244
|
+
if (!isTextSelected) {
|
|
245
|
+
return;
|
|
235
246
|
}
|
|
236
|
-
}
|
|
237
|
-
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
238
|
-
return;
|
|
239
247
|
}
|
|
240
248
|
}
|
|
241
249
|
} else {
|
|
@@ -328,9 +336,8 @@ var TypeAheadPopup = exports.TypeAheadPopup = /*#__PURE__*/_react.default.memo(f
|
|
|
328
336
|
triggerHandler: triggerHandler,
|
|
329
337
|
moreElementsInQuickInsertViewEnabled: moreElementsInQuickInsertViewEnabled,
|
|
330
338
|
api: api,
|
|
331
|
-
showViewMore: showViewMore
|
|
332
|
-
|
|
333
|
-
onClick: onViewMoreClick
|
|
339
|
+
showViewMore: showViewMore,
|
|
340
|
+
onViewMoreClick: onViewMoreClick
|
|
334
341
|
}))));
|
|
335
342
|
});
|
|
336
343
|
TypeAheadPopup.displayName = 'TypeAheadPopup';
|
package/dist/cjs/ui/ViewMore.js
CHANGED
|
@@ -5,7 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.ViewMore = void 0;
|
|
8
|
-
var _react = require("
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _react2 = require("@emotion/react");
|
|
9
10
|
var _reactIntlNext = require("react-intl-next");
|
|
10
11
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
11
12
|
var _showMoreHorizontalEditorMore = _interopRequireDefault(require("@atlaskit/icon/core/migration/show-more-horizontal--editor-more"));
|
|
@@ -15,25 +16,66 @@ var _colors = require("@atlaskit/theme/colors");
|
|
|
15
16
|
* @jsxRuntime classic
|
|
16
17
|
* @jsx jsx
|
|
17
18
|
*/
|
|
19
|
+
|
|
18
20
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
19
21
|
|
|
20
|
-
var buttonStyles = (0,
|
|
22
|
+
var buttonStyles = (0, _react2.css)({
|
|
21
23
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
22
24
|
'& > button:hover': {
|
|
23
25
|
backgroundColor: "var(--ds-background-neutral-subtle-hovered, ".concat(_colors.N30, ")")
|
|
26
|
+
},
|
|
27
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
28
|
+
'& > button:focus': {
|
|
29
|
+
backgroundColor: "var(--ds-background-neutral-subtle-hovered, ".concat(_colors.N30, ")"),
|
|
30
|
+
outline: 'none'
|
|
24
31
|
}
|
|
25
32
|
});
|
|
26
33
|
var ViewMore = exports.ViewMore = function ViewMore(_ref) {
|
|
27
|
-
var onClick = _ref.onClick
|
|
34
|
+
var onClick = _ref.onClick,
|
|
35
|
+
isFocused = _ref.isFocused;
|
|
28
36
|
var _useIntl = (0, _reactIntlNext.useIntl)(),
|
|
29
37
|
formatMessage = _useIntl.formatMessage;
|
|
30
|
-
|
|
38
|
+
var ref = (0, _react.useRef)(null);
|
|
39
|
+
(0, _react.useEffect)(function () {
|
|
40
|
+
if (isFocused && ref.current) {
|
|
41
|
+
ref.current.focus();
|
|
42
|
+
}
|
|
43
|
+
}, [isFocused]);
|
|
44
|
+
(0, _react.useEffect)(function () {
|
|
45
|
+
if (!ref.current) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
var element = ref.current;
|
|
49
|
+
var handleEnter = function handleEnter(e) {
|
|
50
|
+
if (e.key === 'Enter') {
|
|
51
|
+
onClick();
|
|
52
|
+
// Prevent keydown listener in TypeaheadList from handling Enter pressed
|
|
53
|
+
e.stopPropagation();
|
|
54
|
+
} else if (e.key === 'Tab') {
|
|
55
|
+
// TypeaheadList will try to insert selected item on Tab press
|
|
56
|
+
// hence stop propagation to prevent that and treat this as noop
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Ignored via go/ees005
|
|
63
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
64
|
+
element === null || element === void 0 || element.addEventListener('keydown', handleEnter);
|
|
65
|
+
return function () {
|
|
66
|
+
// Ignored via go/ees005
|
|
67
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
68
|
+
element === null || element === void 0 || element.removeEventListener('keydown', handleEnter);
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
return (0, _react2.jsx)(_menu.Section, {
|
|
31
72
|
hasSeparator: true
|
|
32
|
-
}, (0,
|
|
73
|
+
}, (0, _react2.jsx)("span", {
|
|
33
74
|
css: buttonStyles
|
|
34
|
-
}, (0,
|
|
75
|
+
}, (0, _react2.jsx)(_menu.ButtonItem, {
|
|
76
|
+
ref: ref,
|
|
35
77
|
onClick: onClick,
|
|
36
|
-
iconBefore: (0,
|
|
78
|
+
iconBefore: (0, _react2.jsx)(_showMoreHorizontalEditorMore.default, {
|
|
37
79
|
label: ""
|
|
38
80
|
}),
|
|
39
81
|
"aria-describedby": formatMessage(_messages.toolbarInsertBlockMessages.viewMore),
|
|
@@ -9,6 +9,7 @@ exports.WrapperTypeAhead = void 0;
|
|
|
9
9
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _typeAhead = require("@atlaskit/editor-common/type-ahead");
|
|
12
|
+
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
12
13
|
var _updateQuery = require("../pm-plugins/commands/update-query");
|
|
13
14
|
var _itemIsDisabled2 = require("../pm-plugins/item-is-disabled");
|
|
14
15
|
var _utils = require("../pm-plugins/utils");
|
|
@@ -31,6 +32,9 @@ var WrapperTypeAhead = exports.WrapperTypeAhead = /*#__PURE__*/_react.default.me
|
|
|
31
32
|
reopenQuery = _ref.reopenQuery,
|
|
32
33
|
onUndoRedo = _ref.onUndoRedo,
|
|
33
34
|
api = _ref.api;
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
var openElementBrowserModal = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.openElementBrowserModal;
|
|
37
|
+
var showViewMore = (triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.id) === _typeAhead.TypeAheadAvailableNodes.QUICK_INSERT && !!openElementBrowserModal && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1');
|
|
34
38
|
var _useState = (0, _react.useState)(false),
|
|
35
39
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
36
40
|
closed = _useState2[0],
|
|
@@ -41,7 +45,7 @@ var WrapperTypeAhead = exports.WrapperTypeAhead = /*#__PURE__*/_react.default.me
|
|
|
41
45
|
setQuery = _useState4[1];
|
|
42
46
|
var queryRef = (0, _react.useRef)(query);
|
|
43
47
|
var editorViewRef = (0, _react.useRef)(editorView);
|
|
44
|
-
var items = (0, _useLoadItems.useLoadItems)(triggerHandler, editorView, query);
|
|
48
|
+
var items = (0, _useLoadItems.useLoadItems)(triggerHandler, editorView, query, showViewMore);
|
|
45
49
|
(0, _react.useLayoutEffect)(function () {
|
|
46
50
|
queryRef.current = query;
|
|
47
51
|
}, [query]);
|
|
@@ -11,7 +11,7 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
|
11
11
|
var _updateListError = require("../../pm-plugins/commands/update-list-error");
|
|
12
12
|
var _updateListItems = require("../../pm-plugins/commands/update-list-items");
|
|
13
13
|
var EMPTY_LIST_ITEM = [];
|
|
14
|
-
var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler, editorView, query) {
|
|
14
|
+
var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler, editorView, query, showViewMore) {
|
|
15
15
|
var _useState = (0, _react.useState)(EMPTY_LIST_ITEM),
|
|
16
16
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
17
17
|
items = _useState2[0],
|
|
@@ -34,8 +34,11 @@ var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler,
|
|
|
34
34
|
if (componentIsMounted.current) {
|
|
35
35
|
setItems(list);
|
|
36
36
|
}
|
|
37
|
+
var viewMoreItem = {
|
|
38
|
+
title: 'View more'
|
|
39
|
+
};
|
|
37
40
|
queueMicrotask(function () {
|
|
38
|
-
(0, _updateListItems.updateListItem)(list)(view.state, view.dispatch);
|
|
41
|
+
(0, _updateListItems.updateListItem)(showViewMore ? list.concat(viewMoreItem) : list)(view.state, view.dispatch);
|
|
39
42
|
});
|
|
40
43
|
}).catch(function (e) {
|
|
41
44
|
if ((0, _platformFeatureFlags.fg)('platform_editor_offline_editing_ga')) {
|
|
@@ -208,22 +208,31 @@ var TypeAheadPopup = exports.TypeAheadPopup = /*#__PURE__*/_react.default.memo(f
|
|
|
208
208
|
var _window$getSelection2;
|
|
209
209
|
// Check if new focus point is inside the current editor. If it is not we
|
|
210
210
|
// want to close the typeahead popup regardless of text selection state
|
|
211
|
-
var
|
|
211
|
+
var currentFocus = (_window$getSelection2 = window.getSelection()) === null || _window$getSelection2 === void 0 ? void 0 : _window$getSelection2.focusNode; // the focusNode is either TextNode, ElementNode
|
|
212
|
+
// if currentFocus is not HTMLElement, take its parent node as focusNode
|
|
213
|
+
var focusNode = currentFocus instanceof HTMLElement ? currentFocus : currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.parentNode;
|
|
212
214
|
if (focusNode instanceof HTMLElement) {
|
|
213
215
|
var innerEditor = focusNode.closest('.extension-editable-area');
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
216
|
+
if (innerEditor) {
|
|
217
|
+
// When there is no related target, we default to not closing the popup
|
|
218
|
+
var newFocusInsideCurrentEditor = !relatedTarget;
|
|
219
|
+
if (relatedTarget instanceof HTMLElement) {
|
|
220
|
+
if (innerEditor) {
|
|
221
|
+
// check if the new focus is inside inner editor, keep popup opens
|
|
222
|
+
newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
|
|
223
|
+
} else {
|
|
224
|
+
// if the new focus contains current focus node, the popup won't close
|
|
225
|
+
newFocusInsideCurrentEditor = relatedTarget.contains(focusNode);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
// if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
|
|
233
|
+
if (!isTextSelected) {
|
|
234
|
+
return;
|
|
223
235
|
}
|
|
224
|
-
}
|
|
225
|
-
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
226
|
-
return;
|
|
227
236
|
}
|
|
228
237
|
}
|
|
229
238
|
} else {
|
|
@@ -19,6 +19,7 @@ import { TYPE_AHEAD_DECORATION_ELEMENT_ID } from '../pm-plugins/constants';
|
|
|
19
19
|
import { getTypeAheadListAriaLabels, moveSelectedIndex } from '../pm-plugins/utils';
|
|
20
20
|
import { AssistiveText } from './AssistiveText';
|
|
21
21
|
import { TypeAheadListItem } from './TypeAheadListItem';
|
|
22
|
+
import { ViewMore } from './ViewMore';
|
|
22
23
|
const LIST_ITEM_ESTIMATED_HEIGHT = 64;
|
|
23
24
|
const LIST_WIDTH = 320;
|
|
24
25
|
const list = css({
|
|
@@ -52,7 +53,8 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
52
53
|
triggerHandler,
|
|
53
54
|
moreElementsInQuickInsertViewEnabled,
|
|
54
55
|
api,
|
|
55
|
-
showViewMore
|
|
56
|
+
showViewMore,
|
|
57
|
+
onViewMoreClick
|
|
56
58
|
}) => {
|
|
57
59
|
var _decorationElement$qu2;
|
|
58
60
|
const listRef = useRef();
|
|
@@ -63,7 +65,10 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
63
65
|
startIndex: 0,
|
|
64
66
|
stopIndex: 0
|
|
65
67
|
});
|
|
66
|
-
|
|
68
|
+
|
|
69
|
+
// Exclude view more item from the count
|
|
70
|
+
const itemsLength = showViewMore ? items.length - 1 : items.length;
|
|
71
|
+
const estimatedHeight = itemsLength * LIST_ITEM_ESTIMATED_HEIGHT;
|
|
67
72
|
const [height, setHeight] = useState(Math.min(estimatedHeight, fitHeight));
|
|
68
73
|
const [cache, setCache] = useState(new CellMeasurerCache({
|
|
69
74
|
fixedWidth: true,
|
|
@@ -118,7 +123,10 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
118
123
|
// to calculate each height. THen, we can schedule a new frame when this one finishs.
|
|
119
124
|
requestAnimationFrame(() => {
|
|
120
125
|
requestAnimationFrame(() => {
|
|
121
|
-
const
|
|
126
|
+
const isViewMoreSelected = showViewMore && selectedIndex === itemsLength;
|
|
127
|
+
const isSelectedItemVisible = selectedIndex >= lastVisibleStartIndex && selectedIndex <= lastVisibleStopIndex ||
|
|
128
|
+
// view more is always visible, hence no scrolling
|
|
129
|
+
isViewMoreSelected;
|
|
122
130
|
|
|
123
131
|
//Should scroll to the list item only when the selectedIndex >= 0 and item is not visible
|
|
124
132
|
if (!isSelectedItemVisible && selectedIndex !== -1) {
|
|
@@ -128,7 +136,7 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
128
136
|
}
|
|
129
137
|
});
|
|
130
138
|
});
|
|
131
|
-
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex]);
|
|
139
|
+
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex, itemsLength, showViewMore]);
|
|
132
140
|
const onMouseMove = (event, index) => {
|
|
133
141
|
event.preventDefault();
|
|
134
142
|
event.stopPropagation();
|
|
@@ -141,7 +149,10 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
141
149
|
if (!listRef.current) {
|
|
142
150
|
return;
|
|
143
151
|
}
|
|
144
|
-
const
|
|
152
|
+
const isViewMoreSelected = showViewMore && selectedIndex === itemsLength;
|
|
153
|
+
const isSelectedItemVisible = selectedIndex >= lastVisibleStartIndex && selectedIndex <= lastVisibleStopIndex ||
|
|
154
|
+
// view more is always visible, hence no scrolling
|
|
155
|
+
isViewMoreSelected;
|
|
145
156
|
|
|
146
157
|
//Should scroll to the list item only when the selectedIndex >= 0 and item is not visible
|
|
147
158
|
if (!isSelectedItemVisible && selectedIndex !== -1) {
|
|
@@ -149,7 +160,7 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
149
160
|
} else if (selectedIndex === -1) {
|
|
150
161
|
listRef.current.scrollToRow(0);
|
|
151
162
|
}
|
|
152
|
-
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex]);
|
|
163
|
+
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex, itemsLength, showViewMore]);
|
|
153
164
|
useLayoutEffect(() => {
|
|
154
165
|
setCache(new CellMeasurerCache({
|
|
155
166
|
fixedWidth: true,
|
|
@@ -167,13 +178,15 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
167
178
|
});
|
|
168
179
|
}, [items]);
|
|
169
180
|
useLayoutEffect(() => {
|
|
170
|
-
|
|
181
|
+
// Exclude view more item from the count
|
|
182
|
+
const itemsToRender = showViewMore ? items.slice(0, -1) : items;
|
|
183
|
+
const height = Math.min(itemsToRender.reduce((prevValue, currentValue, index) => {
|
|
171
184
|
return prevValue + cache.rowHeight({
|
|
172
185
|
index: index
|
|
173
186
|
});
|
|
174
187
|
}, 0), fitHeight);
|
|
175
188
|
setHeight(height);
|
|
176
|
-
}, [items, cache, fitHeight]);
|
|
189
|
+
}, [items, cache, fitHeight, showViewMore]);
|
|
177
190
|
useLayoutEffect(() => {
|
|
178
191
|
if (!listContainerRef.current) {
|
|
179
192
|
return;
|
|
@@ -228,7 +241,7 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
228
241
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
229
242
|
element === null || element === void 0 ? void 0 : element.removeEventListener('keydown', handleKeyDown);
|
|
230
243
|
};
|
|
231
|
-
}, [editorView.state, focusTargetElement, selectNextItem, selectPreviousItem, selectedIndex, onItemClick,
|
|
244
|
+
}, [editorView.state, focusTargetElement, selectNextItem, selectPreviousItem, selectedIndex, onItemClick, itemsLength]);
|
|
232
245
|
const firstOnlineSupportedRow = useMemo(() => {
|
|
233
246
|
return items.findIndex(item => item.isDisabledOffline !== true);
|
|
234
247
|
}, [items]);
|
|
@@ -255,7 +268,7 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
255
268
|
key: items[index].title,
|
|
256
269
|
item: currentItem,
|
|
257
270
|
firstOnlineSupportedIndex: firstOnlineSupportedRow,
|
|
258
|
-
itemsLength:
|
|
271
|
+
itemsLength: itemsLength,
|
|
259
272
|
itemIndex: index,
|
|
260
273
|
selectedIndex: selectedIndex,
|
|
261
274
|
onItemClick: actions.onItemClick,
|
|
@@ -285,8 +298,10 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
285
298
|
})));
|
|
286
299
|
const ListContent = jsx(List, {
|
|
287
300
|
rowRenderer: renderRow,
|
|
288
|
-
ref: listRef
|
|
289
|
-
|
|
301
|
+
ref: listRef
|
|
302
|
+
// Skip rendering the view more button in the list
|
|
303
|
+
,
|
|
304
|
+
rowCount: itemsLength,
|
|
290
305
|
rowHeight: cache.rowHeight,
|
|
291
306
|
onRowsRendered: onItemsRendered,
|
|
292
307
|
width: LIST_WIDTH,
|
|
@@ -320,8 +335,11 @@ const TypeAheadListComponent = /*#__PURE__*/React.memo(({
|
|
|
320
335
|
}, jsx("div", {
|
|
321
336
|
id: menuGroupId,
|
|
322
337
|
ref: listContainerRef
|
|
323
|
-
}, !showViewMore ||
|
|
324
|
-
|
|
338
|
+
}, !showViewMore || itemsLength ? ListContent : EmptyResultView, showViewMore && onViewMoreClick && jsx(ViewMore, {
|
|
339
|
+
onClick: onViewMoreClick,
|
|
340
|
+
isFocused: selectedIndex === itemsLength
|
|
341
|
+
}), jsx(TypeaheadAssistiveTextPureComponent, {
|
|
342
|
+
numberOfResults: itemsLength.toString()
|
|
325
343
|
})));
|
|
326
344
|
});
|
|
327
345
|
export const TypeAheadList = injectIntl(TypeAheadListComponent);
|
|
@@ -17,7 +17,6 @@ import { N0, N50A, N60A } from '@atlaskit/theme/colors';
|
|
|
17
17
|
import { CloseSelectionOptions, TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE, TYPE_AHEAD_POPUP_CONTENT_CLASS } from '../pm-plugins/constants';
|
|
18
18
|
import { TypeAheadErrorFallback } from './TypeAheadErrorFallback';
|
|
19
19
|
import { TypeAheadList } from './TypeAheadList';
|
|
20
|
-
import { ViewMore } from './ViewMore';
|
|
21
20
|
const DEFAULT_TYPEAHEAD_MENU_HEIGHT = 380;
|
|
22
21
|
const VIEWMORE_BUTTON_HEIGHT = 53;
|
|
23
22
|
const DEFAULT_TYPEAHEAD_MENU_HEIGHT_NEW = 480;
|
|
@@ -209,22 +208,31 @@ export const TypeAheadPopup = /*#__PURE__*/React.memo(props => {
|
|
|
209
208
|
var _window$getSelection2;
|
|
210
209
|
// Check if new focus point is inside the current editor. If it is not we
|
|
211
210
|
// want to close the typeahead popup regardless of text selection state
|
|
212
|
-
const
|
|
211
|
+
const currentFocus = (_window$getSelection2 = window.getSelection()) === null || _window$getSelection2 === void 0 ? void 0 : _window$getSelection2.focusNode; // the focusNode is either TextNode, ElementNode
|
|
212
|
+
// if currentFocus is not HTMLElement, take its parent node as focusNode
|
|
213
|
+
const focusNode = currentFocus instanceof HTMLElement ? currentFocus : currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.parentNode;
|
|
213
214
|
if (focusNode instanceof HTMLElement) {
|
|
214
215
|
const innerEditor = focusNode.closest('.extension-editable-area');
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
216
|
+
if (innerEditor) {
|
|
217
|
+
// When there is no related target, we default to not closing the popup
|
|
218
|
+
let newFocusInsideCurrentEditor = !relatedTarget;
|
|
219
|
+
if (relatedTarget instanceof HTMLElement) {
|
|
220
|
+
if (innerEditor) {
|
|
221
|
+
// check if the new focus is inside inner editor, keep popup opens
|
|
222
|
+
newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
|
|
223
|
+
} else {
|
|
224
|
+
// if the new focus contains current focus node, the popup won't close
|
|
225
|
+
newFocusInsideCurrentEditor = relatedTarget.contains(focusNode);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
// if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
|
|
233
|
+
if (!isTextSelected) {
|
|
234
|
+
return;
|
|
224
235
|
}
|
|
225
|
-
}
|
|
226
|
-
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
227
|
-
return;
|
|
228
236
|
}
|
|
229
237
|
}
|
|
230
238
|
} else {
|
|
@@ -321,9 +329,8 @@ export const TypeAheadPopup = /*#__PURE__*/React.memo(props => {
|
|
|
321
329
|
triggerHandler: triggerHandler,
|
|
322
330
|
moreElementsInQuickInsertViewEnabled: moreElementsInQuickInsertViewEnabled,
|
|
323
331
|
api: api,
|
|
324
|
-
showViewMore: showViewMore
|
|
325
|
-
|
|
326
|
-
onClick: onViewMoreClick
|
|
332
|
+
showViewMore: showViewMore,
|
|
333
|
+
onViewMoreClick: onViewMoreClick
|
|
327
334
|
}))));
|
|
328
335
|
});
|
|
329
336
|
TypeAheadPopup.displayName = 'TypeAheadPopup';
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* @jsxRuntime classic
|
|
3
3
|
* @jsx jsx
|
|
4
4
|
*/
|
|
5
|
+
import { useEffect, useRef } from 'react';
|
|
6
|
+
|
|
5
7
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
6
8
|
import { css, jsx } from '@emotion/react';
|
|
7
9
|
import { useIntl } from 'react-intl-next';
|
|
@@ -13,19 +15,61 @@ const buttonStyles = css({
|
|
|
13
15
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
14
16
|
'& > button:hover': {
|
|
15
17
|
backgroundColor: `var(--ds-background-neutral-subtle-hovered, ${N30})`
|
|
18
|
+
},
|
|
19
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
20
|
+
'& > button:focus': {
|
|
21
|
+
backgroundColor: `var(--ds-background-neutral-subtle-hovered, ${N30})`,
|
|
22
|
+
outline: 'none'
|
|
16
23
|
}
|
|
17
24
|
});
|
|
18
25
|
export const ViewMore = ({
|
|
19
|
-
onClick
|
|
26
|
+
onClick,
|
|
27
|
+
isFocused
|
|
20
28
|
}) => {
|
|
21
29
|
const {
|
|
22
30
|
formatMessage
|
|
23
31
|
} = useIntl();
|
|
32
|
+
const ref = useRef(null);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (isFocused && ref.current) {
|
|
35
|
+
ref.current.focus();
|
|
36
|
+
}
|
|
37
|
+
}, [isFocused]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!ref.current) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const {
|
|
43
|
+
current: element
|
|
44
|
+
} = ref;
|
|
45
|
+
const handleEnter = e => {
|
|
46
|
+
if (e.key === 'Enter') {
|
|
47
|
+
onClick();
|
|
48
|
+
// Prevent keydown listener in TypeaheadList from handling Enter pressed
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
} else if (e.key === 'Tab') {
|
|
51
|
+
// TypeaheadList will try to insert selected item on Tab press
|
|
52
|
+
// hence stop propagation to prevent that and treat this as noop
|
|
53
|
+
e.stopPropagation();
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Ignored via go/ees005
|
|
59
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
60
|
+
element === null || element === void 0 ? void 0 : element.addEventListener('keydown', handleEnter);
|
|
61
|
+
return () => {
|
|
62
|
+
// Ignored via go/ees005
|
|
63
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
64
|
+
element === null || element === void 0 ? void 0 : element.removeEventListener('keydown', handleEnter);
|
|
65
|
+
};
|
|
66
|
+
});
|
|
24
67
|
return jsx(Section, {
|
|
25
68
|
hasSeparator: true
|
|
26
69
|
}, jsx("span", {
|
|
27
70
|
css: buttonStyles
|
|
28
71
|
}, jsx(ButtonItem, {
|
|
72
|
+
ref: ref,
|
|
29
73
|
onClick: onClick,
|
|
30
74
|
iconBefore: jsx(ShowMoreHorizontalIcon, {
|
|
31
75
|
label: ""
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
|
|
2
|
+
import { SelectItemMode, TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
|
|
3
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
3
4
|
import { updateQuery } from '../pm-plugins/commands/update-query';
|
|
4
5
|
import { itemIsDisabled } from '../pm-plugins/item-is-disabled';
|
|
5
6
|
import { getPluginState, moveSelectedIndex, skipForwardToSafeItem } from '../pm-plugins/utils';
|
|
@@ -21,11 +22,14 @@ export const WrapperTypeAhead = /*#__PURE__*/React.memo(({
|
|
|
21
22
|
onUndoRedo,
|
|
22
23
|
api
|
|
23
24
|
}) => {
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
const openElementBrowserModal = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.openElementBrowserModal;
|
|
27
|
+
const showViewMore = (triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.id) === TypeAheadAvailableNodes.QUICK_INSERT && !!openElementBrowserModal && editorExperiment('platform_editor_controls', 'variant1');
|
|
24
28
|
const [closed, setClosed] = useState(false);
|
|
25
29
|
const [query, setQuery] = useState(reopenQuery || '');
|
|
26
30
|
const queryRef = useRef(query);
|
|
27
31
|
const editorViewRef = useRef(editorView);
|
|
28
|
-
const items = useLoadItems(triggerHandler, editorView, query);
|
|
32
|
+
const items = useLoadItems(triggerHandler, editorView, query, showViewMore);
|
|
29
33
|
useLayoutEffect(() => {
|
|
30
34
|
queryRef.current = query;
|
|
31
35
|
}, [query]);
|
|
@@ -3,7 +3,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
|
|
|
3
3
|
import { updateListError } from '../../pm-plugins/commands/update-list-error';
|
|
4
4
|
import { updateListItem } from '../../pm-plugins/commands/update-list-items';
|
|
5
5
|
const EMPTY_LIST_ITEM = [];
|
|
6
|
-
export const useLoadItems = (triggerHandler, editorView, query) => {
|
|
6
|
+
export const useLoadItems = (triggerHandler, editorView, query, showViewMore) => {
|
|
7
7
|
const [items, setItems] = useState(EMPTY_LIST_ITEM);
|
|
8
8
|
const componentIsMounted = useRef(true);
|
|
9
9
|
const editorViewRef = useRef(editorView);
|
|
@@ -25,8 +25,11 @@ export const useLoadItems = (triggerHandler, editorView, query) => {
|
|
|
25
25
|
if (componentIsMounted.current) {
|
|
26
26
|
setItems(list);
|
|
27
27
|
}
|
|
28
|
+
const viewMoreItem = {
|
|
29
|
+
title: 'View more'
|
|
30
|
+
};
|
|
28
31
|
queueMicrotask(() => {
|
|
29
|
-
updateListItem(list)(view.state, view.dispatch);
|
|
32
|
+
updateListItem(showViewMore ? list.concat(viewMoreItem) : list)(view.state, view.dispatch);
|
|
30
33
|
});
|
|
31
34
|
}).catch(e => {
|
|
32
35
|
if (fg('platform_editor_offline_editing_ga')) {
|
|
@@ -199,22 +199,31 @@ export const TypeAheadPopup = /*#__PURE__*/React.memo(props => {
|
|
|
199
199
|
var _window$getSelection2;
|
|
200
200
|
// Check if new focus point is inside the current editor. If it is not we
|
|
201
201
|
// want to close the typeahead popup regardless of text selection state
|
|
202
|
-
const
|
|
202
|
+
const currentFocus = (_window$getSelection2 = window.getSelection()) === null || _window$getSelection2 === void 0 ? void 0 : _window$getSelection2.focusNode; // the focusNode is either TextNode, ElementNode
|
|
203
|
+
// if currentFocus is not HTMLElement, take its parent node as focusNode
|
|
204
|
+
const focusNode = currentFocus instanceof HTMLElement ? currentFocus : currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.parentNode;
|
|
203
205
|
if (focusNode instanceof HTMLElement) {
|
|
204
206
|
const innerEditor = focusNode.closest('.extension-editable-area');
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
207
|
+
if (innerEditor) {
|
|
208
|
+
// When there is no related target, we default to not closing the popup
|
|
209
|
+
let newFocusInsideCurrentEditor = !relatedTarget;
|
|
210
|
+
if (relatedTarget instanceof HTMLElement) {
|
|
211
|
+
if (innerEditor) {
|
|
212
|
+
// check if the new focus is inside inner editor, keep popup opens
|
|
213
|
+
newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
|
|
214
|
+
} else {
|
|
215
|
+
// if the new focus contains current focus node, the popup won't close
|
|
216
|
+
newFocusInsideCurrentEditor = relatedTarget.contains(focusNode);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
// if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
|
|
224
|
+
if (!isTextSelected) {
|
|
225
|
+
return;
|
|
214
226
|
}
|
|
215
|
-
}
|
|
216
|
-
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
217
|
-
return;
|
|
218
227
|
}
|
|
219
228
|
}
|
|
220
229
|
} else {
|
|
@@ -20,6 +20,7 @@ import { TYPE_AHEAD_DECORATION_ELEMENT_ID } from '../pm-plugins/constants';
|
|
|
20
20
|
import { getTypeAheadListAriaLabels, moveSelectedIndex } from '../pm-plugins/utils';
|
|
21
21
|
import { AssistiveText } from './AssistiveText';
|
|
22
22
|
import { TypeAheadListItem } from './TypeAheadListItem';
|
|
23
|
+
import { ViewMore } from './ViewMore';
|
|
23
24
|
var LIST_ITEM_ESTIMATED_HEIGHT = 64;
|
|
24
25
|
var LIST_WIDTH = 320;
|
|
25
26
|
var list = css({
|
|
@@ -53,7 +54,8 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
53
54
|
triggerHandler = _ref2.triggerHandler,
|
|
54
55
|
moreElementsInQuickInsertViewEnabled = _ref2.moreElementsInQuickInsertViewEnabled,
|
|
55
56
|
api = _ref2.api,
|
|
56
|
-
showViewMore = _ref2.showViewMore
|
|
57
|
+
showViewMore = _ref2.showViewMore,
|
|
58
|
+
onViewMoreClick = _ref2.onViewMoreClick;
|
|
57
59
|
var listRef = useRef();
|
|
58
60
|
var listContainerRef = useRef(null);
|
|
59
61
|
var lastVisibleIndexes = useRef({
|
|
@@ -62,7 +64,10 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
62
64
|
startIndex: 0,
|
|
63
65
|
stopIndex: 0
|
|
64
66
|
});
|
|
65
|
-
|
|
67
|
+
|
|
68
|
+
// Exclude view more item from the count
|
|
69
|
+
var itemsLength = showViewMore ? items.length - 1 : items.length;
|
|
70
|
+
var estimatedHeight = itemsLength * LIST_ITEM_ESTIMATED_HEIGHT;
|
|
66
71
|
var _useState = useState(Math.min(estimatedHeight, fitHeight)),
|
|
67
72
|
_useState2 = _slicedToArray(_useState, 2),
|
|
68
73
|
height = _useState2[0],
|
|
@@ -128,7 +133,10 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
128
133
|
// to calculate each height. THen, we can schedule a new frame when this one finishs.
|
|
129
134
|
requestAnimationFrame(function () {
|
|
130
135
|
requestAnimationFrame(function () {
|
|
131
|
-
var
|
|
136
|
+
var isViewMoreSelected = showViewMore && selectedIndex === itemsLength;
|
|
137
|
+
var isSelectedItemVisible = selectedIndex >= lastVisibleStartIndex && selectedIndex <= lastVisibleStopIndex ||
|
|
138
|
+
// view more is always visible, hence no scrolling
|
|
139
|
+
isViewMoreSelected;
|
|
132
140
|
|
|
133
141
|
//Should scroll to the list item only when the selectedIndex >= 0 and item is not visible
|
|
134
142
|
if (!isSelectedItemVisible && selectedIndex !== -1) {
|
|
@@ -138,7 +146,7 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
138
146
|
}
|
|
139
147
|
});
|
|
140
148
|
});
|
|
141
|
-
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex]);
|
|
149
|
+
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex, itemsLength, showViewMore]);
|
|
142
150
|
var _onMouseMove = function onMouseMove(event, index) {
|
|
143
151
|
event.preventDefault();
|
|
144
152
|
event.stopPropagation();
|
|
@@ -151,7 +159,10 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
151
159
|
if (!listRef.current) {
|
|
152
160
|
return;
|
|
153
161
|
}
|
|
154
|
-
var
|
|
162
|
+
var isViewMoreSelected = showViewMore && selectedIndex === itemsLength;
|
|
163
|
+
var isSelectedItemVisible = selectedIndex >= lastVisibleStartIndex && selectedIndex <= lastVisibleStopIndex ||
|
|
164
|
+
// view more is always visible, hence no scrolling
|
|
165
|
+
isViewMoreSelected;
|
|
155
166
|
|
|
156
167
|
//Should scroll to the list item only when the selectedIndex >= 0 and item is not visible
|
|
157
168
|
if (!isSelectedItemVisible && selectedIndex !== -1) {
|
|
@@ -159,7 +170,7 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
159
170
|
} else if (selectedIndex === -1) {
|
|
160
171
|
listRef.current.scrollToRow(0);
|
|
161
172
|
}
|
|
162
|
-
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex]);
|
|
173
|
+
}, [selectedIndex, lastVisibleStartIndex, lastVisibleStopIndex, itemsLength, showViewMore]);
|
|
163
174
|
useLayoutEffect(function () {
|
|
164
175
|
setCache(new CellMeasurerCache({
|
|
165
176
|
fixedWidth: true,
|
|
@@ -177,13 +188,15 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
177
188
|
});
|
|
178
189
|
}, [items]);
|
|
179
190
|
useLayoutEffect(function () {
|
|
180
|
-
|
|
191
|
+
// Exclude view more item from the count
|
|
192
|
+
var itemsToRender = showViewMore ? items.slice(0, -1) : items;
|
|
193
|
+
var height = Math.min(itemsToRender.reduce(function (prevValue, currentValue, index) {
|
|
181
194
|
return prevValue + cache.rowHeight({
|
|
182
195
|
index: index
|
|
183
196
|
});
|
|
184
197
|
}, 0), fitHeight);
|
|
185
198
|
setHeight(height);
|
|
186
|
-
}, [items, cache, fitHeight]);
|
|
199
|
+
}, [items, cache, fitHeight, showViewMore]);
|
|
187
200
|
useLayoutEffect(function () {
|
|
188
201
|
if (!listContainerRef.current) {
|
|
189
202
|
return;
|
|
@@ -236,7 +249,7 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
236
249
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
237
250
|
element === null || element === void 0 || element.removeEventListener('keydown', handleKeyDown);
|
|
238
251
|
};
|
|
239
|
-
}, [editorView.state, focusTargetElement, selectNextItem, selectPreviousItem, selectedIndex, onItemClick,
|
|
252
|
+
}, [editorView.state, focusTargetElement, selectNextItem, selectPreviousItem, selectedIndex, onItemClick, itemsLength]);
|
|
240
253
|
var firstOnlineSupportedRow = useMemo(function () {
|
|
241
254
|
return items.findIndex(function (item) {
|
|
242
255
|
return item.isDisabledOffline !== true;
|
|
@@ -266,7 +279,7 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
266
279
|
key: items[index].title,
|
|
267
280
|
item: currentItem,
|
|
268
281
|
firstOnlineSupportedIndex: firstOnlineSupportedRow,
|
|
269
|
-
itemsLength:
|
|
282
|
+
itemsLength: itemsLength,
|
|
270
283
|
itemIndex: index,
|
|
271
284
|
selectedIndex: selectedIndex,
|
|
272
285
|
onItemClick: actions.onItemClick,
|
|
@@ -296,8 +309,10 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
296
309
|
})));
|
|
297
310
|
var ListContent = jsx(List, {
|
|
298
311
|
rowRenderer: renderRow,
|
|
299
|
-
ref: listRef
|
|
300
|
-
|
|
312
|
+
ref: listRef
|
|
313
|
+
// Skip rendering the view more button in the list
|
|
314
|
+
,
|
|
315
|
+
rowCount: itemsLength,
|
|
301
316
|
rowHeight: cache.rowHeight,
|
|
302
317
|
onRowsRendered: onItemsRendered,
|
|
303
318
|
width: LIST_WIDTH,
|
|
@@ -331,8 +346,11 @@ var TypeAheadListComponent = /*#__PURE__*/React.memo(function (_ref2) {
|
|
|
331
346
|
}, jsx("div", {
|
|
332
347
|
id: menuGroupId,
|
|
333
348
|
ref: listContainerRef
|
|
334
|
-
}, !showViewMore ||
|
|
335
|
-
|
|
349
|
+
}, !showViewMore || itemsLength ? ListContent : EmptyResultView, showViewMore && onViewMoreClick && jsx(ViewMore, {
|
|
350
|
+
onClick: onViewMoreClick,
|
|
351
|
+
isFocused: selectedIndex === itemsLength
|
|
352
|
+
}), jsx(TypeaheadAssistiveTextPureComponent, {
|
|
353
|
+
numberOfResults: itemsLength.toString()
|
|
336
354
|
})));
|
|
337
355
|
});
|
|
338
356
|
export var TypeAheadList = injectIntl(TypeAheadListComponent);
|
|
@@ -18,7 +18,6 @@ import { N0, N50A, N60A } from '@atlaskit/theme/colors';
|
|
|
18
18
|
import { CloseSelectionOptions, TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE, TYPE_AHEAD_POPUP_CONTENT_CLASS } from '../pm-plugins/constants';
|
|
19
19
|
import { TypeAheadErrorFallback } from './TypeAheadErrorFallback';
|
|
20
20
|
import { TypeAheadList } from './TypeAheadList';
|
|
21
|
-
import { ViewMore } from './ViewMore';
|
|
22
21
|
var DEFAULT_TYPEAHEAD_MENU_HEIGHT = 380;
|
|
23
22
|
var VIEWMORE_BUTTON_HEIGHT = 53;
|
|
24
23
|
var DEFAULT_TYPEAHEAD_MENU_HEIGHT_NEW = 480;
|
|
@@ -209,22 +208,31 @@ export var TypeAheadPopup = /*#__PURE__*/React.memo(function (props) {
|
|
|
209
208
|
var _window$getSelection2;
|
|
210
209
|
// Check if new focus point is inside the current editor. If it is not we
|
|
211
210
|
// want to close the typeahead popup regardless of text selection state
|
|
212
|
-
var
|
|
211
|
+
var currentFocus = (_window$getSelection2 = window.getSelection()) === null || _window$getSelection2 === void 0 ? void 0 : _window$getSelection2.focusNode; // the focusNode is either TextNode, ElementNode
|
|
212
|
+
// if currentFocus is not HTMLElement, take its parent node as focusNode
|
|
213
|
+
var focusNode = currentFocus instanceof HTMLElement ? currentFocus : currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.parentNode;
|
|
213
214
|
if (focusNode instanceof HTMLElement) {
|
|
214
215
|
var innerEditor = focusNode.closest('.extension-editable-area');
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
216
|
+
if (innerEditor) {
|
|
217
|
+
// When there is no related target, we default to not closing the popup
|
|
218
|
+
var newFocusInsideCurrentEditor = !relatedTarget;
|
|
219
|
+
if (relatedTarget instanceof HTMLElement) {
|
|
220
|
+
if (innerEditor) {
|
|
221
|
+
// check if the new focus is inside inner editor, keep popup opens
|
|
222
|
+
newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
|
|
223
|
+
} else {
|
|
224
|
+
// if the new focus contains current focus node, the popup won't close
|
|
225
|
+
newFocusInsideCurrentEditor = relatedTarget.contains(focusNode);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
// if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
|
|
233
|
+
if (!isTextSelected) {
|
|
234
|
+
return;
|
|
224
235
|
}
|
|
225
|
-
}
|
|
226
|
-
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
227
|
-
return;
|
|
228
236
|
}
|
|
229
237
|
}
|
|
230
238
|
} else {
|
|
@@ -317,9 +325,8 @@ export var TypeAheadPopup = /*#__PURE__*/React.memo(function (props) {
|
|
|
317
325
|
triggerHandler: triggerHandler,
|
|
318
326
|
moreElementsInQuickInsertViewEnabled: moreElementsInQuickInsertViewEnabled,
|
|
319
327
|
api: api,
|
|
320
|
-
showViewMore: showViewMore
|
|
321
|
-
|
|
322
|
-
onClick: onViewMoreClick
|
|
328
|
+
showViewMore: showViewMore,
|
|
329
|
+
onViewMoreClick: onViewMoreClick
|
|
323
330
|
}))));
|
|
324
331
|
});
|
|
325
332
|
TypeAheadPopup.displayName = 'TypeAheadPopup';
|
package/dist/esm/ui/ViewMore.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* @jsxRuntime classic
|
|
3
3
|
* @jsx jsx
|
|
4
4
|
*/
|
|
5
|
+
import { useEffect, useRef } from 'react';
|
|
6
|
+
|
|
5
7
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
6
8
|
import { css, jsx } from '@emotion/react';
|
|
7
9
|
import { useIntl } from 'react-intl-next';
|
|
@@ -13,17 +15,57 @@ var buttonStyles = css({
|
|
|
13
15
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
14
16
|
'& > button:hover': {
|
|
15
17
|
backgroundColor: "var(--ds-background-neutral-subtle-hovered, ".concat(N30, ")")
|
|
18
|
+
},
|
|
19
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
|
|
20
|
+
'& > button:focus': {
|
|
21
|
+
backgroundColor: "var(--ds-background-neutral-subtle-hovered, ".concat(N30, ")"),
|
|
22
|
+
outline: 'none'
|
|
16
23
|
}
|
|
17
24
|
});
|
|
18
25
|
export var ViewMore = function ViewMore(_ref) {
|
|
19
|
-
var onClick = _ref.onClick
|
|
26
|
+
var onClick = _ref.onClick,
|
|
27
|
+
isFocused = _ref.isFocused;
|
|
20
28
|
var _useIntl = useIntl(),
|
|
21
29
|
formatMessage = _useIntl.formatMessage;
|
|
30
|
+
var ref = useRef(null);
|
|
31
|
+
useEffect(function () {
|
|
32
|
+
if (isFocused && ref.current) {
|
|
33
|
+
ref.current.focus();
|
|
34
|
+
}
|
|
35
|
+
}, [isFocused]);
|
|
36
|
+
useEffect(function () {
|
|
37
|
+
if (!ref.current) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
var element = ref.current;
|
|
41
|
+
var handleEnter = function handleEnter(e) {
|
|
42
|
+
if (e.key === 'Enter') {
|
|
43
|
+
onClick();
|
|
44
|
+
// Prevent keydown listener in TypeaheadList from handling Enter pressed
|
|
45
|
+
e.stopPropagation();
|
|
46
|
+
} else if (e.key === 'Tab') {
|
|
47
|
+
// TypeaheadList will try to insert selected item on Tab press
|
|
48
|
+
// hence stop propagation to prevent that and treat this as noop
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Ignored via go/ees005
|
|
55
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
56
|
+
element === null || element === void 0 || element.addEventListener('keydown', handleEnter);
|
|
57
|
+
return function () {
|
|
58
|
+
// Ignored via go/ees005
|
|
59
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
60
|
+
element === null || element === void 0 || element.removeEventListener('keydown', handleEnter);
|
|
61
|
+
};
|
|
62
|
+
});
|
|
22
63
|
return jsx(Section, {
|
|
23
64
|
hasSeparator: true
|
|
24
65
|
}, jsx("span", {
|
|
25
66
|
css: buttonStyles
|
|
26
67
|
}, jsx(ButtonItem, {
|
|
68
|
+
ref: ref,
|
|
27
69
|
onClick: onClick,
|
|
28
70
|
iconBefore: jsx(ShowMoreHorizontalIcon, {
|
|
29
71
|
label: ""
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
2
|
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
|
|
3
|
+
import { SelectItemMode, TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
|
|
4
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
4
5
|
import { updateQuery } from '../pm-plugins/commands/update-query';
|
|
5
6
|
import { itemIsDisabled as _itemIsDisabled } from '../pm-plugins/item-is-disabled';
|
|
6
7
|
import { getPluginState, moveSelectedIndex, skipForwardToSafeItem } from '../pm-plugins/utils';
|
|
@@ -21,6 +22,9 @@ export var WrapperTypeAhead = /*#__PURE__*/React.memo(function (_ref) {
|
|
|
21
22
|
reopenQuery = _ref.reopenQuery,
|
|
22
23
|
onUndoRedo = _ref.onUndoRedo,
|
|
23
24
|
api = _ref.api;
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
var openElementBrowserModal = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.openElementBrowserModal;
|
|
27
|
+
var showViewMore = (triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.id) === TypeAheadAvailableNodes.QUICK_INSERT && !!openElementBrowserModal && editorExperiment('platform_editor_controls', 'variant1');
|
|
24
28
|
var _useState = useState(false),
|
|
25
29
|
_useState2 = _slicedToArray(_useState, 2),
|
|
26
30
|
closed = _useState2[0],
|
|
@@ -31,7 +35,7 @@ export var WrapperTypeAhead = /*#__PURE__*/React.memo(function (_ref) {
|
|
|
31
35
|
setQuery = _useState4[1];
|
|
32
36
|
var queryRef = useRef(query);
|
|
33
37
|
var editorViewRef = useRef(editorView);
|
|
34
|
-
var items = useLoadItems(triggerHandler, editorView, query);
|
|
38
|
+
var items = useLoadItems(triggerHandler, editorView, query, showViewMore);
|
|
35
39
|
useLayoutEffect(function () {
|
|
36
40
|
queryRef.current = query;
|
|
37
41
|
}, [query]);
|
|
@@ -4,7 +4,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
|
|
|
4
4
|
import { updateListError } from '../../pm-plugins/commands/update-list-error';
|
|
5
5
|
import { updateListItem } from '../../pm-plugins/commands/update-list-items';
|
|
6
6
|
var EMPTY_LIST_ITEM = [];
|
|
7
|
-
export var useLoadItems = function useLoadItems(triggerHandler, editorView, query) {
|
|
7
|
+
export var useLoadItems = function useLoadItems(triggerHandler, editorView, query, showViewMore) {
|
|
8
8
|
var _useState = useState(EMPTY_LIST_ITEM),
|
|
9
9
|
_useState2 = _slicedToArray(_useState, 2),
|
|
10
10
|
items = _useState2[0],
|
|
@@ -27,8 +27,11 @@ export var useLoadItems = function useLoadItems(triggerHandler, editorView, quer
|
|
|
27
27
|
if (componentIsMounted.current) {
|
|
28
28
|
setItems(list);
|
|
29
29
|
}
|
|
30
|
+
var viewMoreItem = {
|
|
31
|
+
title: 'View more'
|
|
32
|
+
};
|
|
30
33
|
queueMicrotask(function () {
|
|
31
|
-
updateListItem(list)(view.state, view.dispatch);
|
|
34
|
+
updateListItem(showViewMore ? list.concat(viewMoreItem) : list)(view.state, view.dispatch);
|
|
32
35
|
});
|
|
33
36
|
}).catch(function (e) {
|
|
34
37
|
if (fg('platform_editor_offline_editing_ga')) {
|
|
@@ -198,22 +198,31 @@ export var TypeAheadPopup = /*#__PURE__*/React.memo(function (props) {
|
|
|
198
198
|
var _window$getSelection2;
|
|
199
199
|
// Check if new focus point is inside the current editor. If it is not we
|
|
200
200
|
// want to close the typeahead popup regardless of text selection state
|
|
201
|
-
var
|
|
201
|
+
var currentFocus = (_window$getSelection2 = window.getSelection()) === null || _window$getSelection2 === void 0 ? void 0 : _window$getSelection2.focusNode; // the focusNode is either TextNode, ElementNode
|
|
202
|
+
// if currentFocus is not HTMLElement, take its parent node as focusNode
|
|
203
|
+
var focusNode = currentFocus instanceof HTMLElement ? currentFocus : currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.parentNode;
|
|
202
204
|
if (focusNode instanceof HTMLElement) {
|
|
203
205
|
var innerEditor = focusNode.closest('.extension-editable-area');
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
if (innerEditor) {
|
|
207
|
+
// When there is no related target, we default to not closing the popup
|
|
208
|
+
var newFocusInsideCurrentEditor = !relatedTarget;
|
|
209
|
+
if (relatedTarget instanceof HTMLElement) {
|
|
210
|
+
if (innerEditor) {
|
|
211
|
+
// check if the new focus is inside inner editor, keep popup opens
|
|
212
|
+
newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
|
|
213
|
+
} else {
|
|
214
|
+
// if the new focus contains current focus node, the popup won't close
|
|
215
|
+
newFocusInsideCurrentEditor = relatedTarget.contains(focusNode);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
// if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
|
|
223
|
+
if (!isTextSelected) {
|
|
224
|
+
return;
|
|
213
225
|
}
|
|
214
|
-
}
|
|
215
|
-
if (!isTextSelected && newFocusInsideCurrentEditor) {
|
|
216
|
-
return;
|
|
217
226
|
}
|
|
218
227
|
}
|
|
219
228
|
} else {
|
|
@@ -20,6 +20,7 @@ export declare const TypeAheadList: React.FC<import("react-intl-next").WithIntlP
|
|
|
20
20
|
moreElementsInQuickInsertViewEnabled?: boolean | undefined;
|
|
21
21
|
api: ExtractInjectionAPI<TypeAheadPlugin> | undefined;
|
|
22
22
|
showViewMore?: boolean | undefined;
|
|
23
|
+
onViewMoreClick?: (() => void) | undefined;
|
|
23
24
|
} & WrappedComponentProps>> & {
|
|
24
25
|
WrappedComponent: React.ComponentType<{
|
|
25
26
|
items: Array<TypeAheadItem>;
|
|
@@ -32,5 +33,6 @@ export declare const TypeAheadList: React.FC<import("react-intl-next").WithIntlP
|
|
|
32
33
|
moreElementsInQuickInsertViewEnabled?: boolean | undefined;
|
|
33
34
|
api: ExtractInjectionAPI<TypeAheadPlugin> | undefined;
|
|
34
35
|
showViewMore?: boolean | undefined;
|
|
36
|
+
onViewMoreClick?: (() => void) | undefined;
|
|
35
37
|
} & WrappedComponentProps>;
|
|
36
38
|
};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jsxRuntime classic
|
|
3
|
-
* @jsx jsx
|
|
4
|
-
*/
|
|
5
1
|
import { jsx } from '@emotion/react';
|
|
6
|
-
export declare const ViewMore: ({ onClick, }: {
|
|
7
|
-
onClick: (
|
|
2
|
+
export declare const ViewMore: ({ onClick, isFocused }: {
|
|
3
|
+
onClick: () => void;
|
|
4
|
+
isFocused: boolean;
|
|
8
5
|
}) => jsx.JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { TypeAheadHandler, TypeAheadItem } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
-
export declare const useLoadItems: (triggerHandler: TypeAheadHandler, editorView: EditorView, query: string) => Array<TypeAheadItem>;
|
|
3
|
+
export declare const useLoadItems: (triggerHandler: TypeAheadHandler, editorView: EditorView, query: string, showViewMore?: boolean) => Array<TypeAheadItem>;
|
|
@@ -20,6 +20,7 @@ export declare const TypeAheadList: React.FC<import("react-intl-next").WithIntlP
|
|
|
20
20
|
moreElementsInQuickInsertViewEnabled?: boolean | undefined;
|
|
21
21
|
api: ExtractInjectionAPI<TypeAheadPlugin> | undefined;
|
|
22
22
|
showViewMore?: boolean | undefined;
|
|
23
|
+
onViewMoreClick?: (() => void) | undefined;
|
|
23
24
|
} & WrappedComponentProps>> & {
|
|
24
25
|
WrappedComponent: React.ComponentType<{
|
|
25
26
|
items: Array<TypeAheadItem>;
|
|
@@ -32,5 +33,6 @@ export declare const TypeAheadList: React.FC<import("react-intl-next").WithIntlP
|
|
|
32
33
|
moreElementsInQuickInsertViewEnabled?: boolean | undefined;
|
|
33
34
|
api: ExtractInjectionAPI<TypeAheadPlugin> | undefined;
|
|
34
35
|
showViewMore?: boolean | undefined;
|
|
36
|
+
onViewMoreClick?: (() => void) | undefined;
|
|
35
37
|
} & WrappedComponentProps>;
|
|
36
38
|
};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jsxRuntime classic
|
|
3
|
-
* @jsx jsx
|
|
4
|
-
*/
|
|
5
1
|
import { jsx } from '@emotion/react';
|
|
6
|
-
export declare const ViewMore: ({ onClick, }: {
|
|
7
|
-
onClick: (
|
|
2
|
+
export declare const ViewMore: ({ onClick, isFocused }: {
|
|
3
|
+
onClick: () => void;
|
|
4
|
+
isFocused: boolean;
|
|
8
5
|
}) => jsx.JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { TypeAheadHandler, TypeAheadItem } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
-
export declare const useLoadItems: (triggerHandler: TypeAheadHandler, editorView: EditorView, query: string) => Array<TypeAheadItem>;
|
|
3
|
+
export declare const useLoadItems: (triggerHandler: TypeAheadHandler, editorView: EditorView, query: string, showViewMore?: boolean) => Array<TypeAheadItem>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-type-ahead",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "Type-ahead plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@atlaskit/adf-schema": "^47.6.0",
|
|
37
|
-
"@atlaskit/editor-common": "^101.
|
|
37
|
+
"@atlaskit/editor-common": "^101.1.0",
|
|
38
38
|
"@atlaskit/editor-element-browser": "^0.1.0",
|
|
39
39
|
"@atlaskit/editor-plugin-analytics": "^2.1.0",
|
|
40
40
|
"@atlaskit/editor-plugin-connectivity": "^2.0.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
48
48
|
"@atlaskit/primitives": "^14.1.0",
|
|
49
49
|
"@atlaskit/prosemirror-input-rules": "^3.3.0",
|
|
50
|
-
"@atlaskit/theme": "^
|
|
50
|
+
"@atlaskit/theme": "^18.0.0",
|
|
51
51
|
"@atlaskit/tmp-editor-statsig": "^3.4.0",
|
|
52
52
|
"@atlaskit/tokens": "^4.3.0",
|
|
53
53
|
"@babel/runtime": "^7.0.0",
|