@atlaskit/editor-plugin-type-ahead 6.5.11 → 6.5.13

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.
@@ -1,321 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- var _typeof = require("@babel/runtime/helpers/typeof");
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.TypeAheadPopup = void 0;
9
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
- var _react = _interopRequireWildcard(require("react"));
11
- var _react2 = require("@emotion/react");
12
- var _rafSchd = _interopRequireDefault(require("raf-schd"));
13
- var _reactIntlNext = require("react-intl-next");
14
- var _analytics = require("@atlaskit/editor-common/analytics");
15
- var _messages = require("@atlaskit/editor-common/messages");
16
- var _ui = require("@atlaskit/editor-common/ui");
17
- var _editorElementBrowser = require("@atlaskit/editor-element-browser");
18
- var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
19
- var _add = _interopRequireDefault(require("@atlaskit/icon/core/add"));
20
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
21
- var _colors = require("@atlaskit/theme/colors");
22
- var _constants = require("../../pm-plugins/constants");
23
- var _TypeAheadErrorFallback = require("../TypeAheadErrorFallback");
24
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
25
- /* eslint-disable @atlaskit/ui-styling-standard/use-compiled */
26
- /**
27
- * @jsxRuntime classic
28
- * @jsx jsx
29
- */
30
-
31
- // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
32
-
33
- var DEFAULT_TYPEAHEAD_MENU_HEIGHT = 520;
34
- // const DEFAULT_TYPEAHEAD_MENU_HEIGHT_NEW = 480;
35
-
36
- var ITEM_PADDING = 12;
37
- var INSERT_PANEL_WIDTH = 320;
38
- var typeAheadContent = (0, _react2.css)({
39
- background: "var(--ds-surface-overlay, ".concat(_colors.N0, ")"),
40
- borderRadius: "var(--ds-radius-small, 3px)",
41
- boxShadow: "var(--ds-shadow-overlay, ".concat("0 0 1px ".concat(_colors.N60A, ", 0 4px 8px -2px ").concat(_colors.N50A), ")"),
42
- padding: "var(--ds-space-050, 4px)".concat(" 0"),
43
- width: '280px',
44
- maxHeight: '520px' /* ~5.5 visibile items */,
45
- overflowY: 'auto',
46
- MsOverflowStyle: '-ms-autohiding-scrollbar',
47
- position: 'relative'
48
- });
49
- // const typeAheadContentOverride = css({
50
- // maxHeight: `${DEFAULT_TYPEAHEAD_MENU_HEIGHT_NEW}px`,
51
- // });
52
-
53
- var OFFSET = [0, 8];
54
- var TypeAheadPopup = exports.TypeAheadPopup = /*#__PURE__*/_react.default.memo(function (props) {
55
- var triggerHandler = props.triggerHandler,
56
- anchorElement = props.anchorElement,
57
- popupsMountPoint = props.popupsMountPoint,
58
- popupsBoundariesElement = props.popupsBoundariesElement,
59
- popupsScrollableElement = props.popupsScrollableElement,
60
- items = props.items,
61
- errorInfo = props.errorInfo,
62
- onItemInsert = props.onItemInsert,
63
- isEmptyQuery = props.isEmptyQuery,
64
- cancel = props.cancel,
65
- api = props.api,
66
- query = props.query,
67
- setSelectedItem = props.setSelectedItem;
68
- var ref = (0, _react.useRef)(null);
69
- var _useIntl = (0, _reactIntlNext.useIntl)(),
70
- formatMessage = _useIntl.formatMessage;
71
- var defaultMenuHeight = DEFAULT_TYPEAHEAD_MENU_HEIGHT;
72
- var startTime = (0, _react.useMemo)(function () {
73
- return performance.now();
74
- },
75
- // In case those props changes
76
- // we need to recreate the startTime
77
- [items, isEmptyQuery, triggerHandler] // eslint-disable-line react-hooks/exhaustive-deps
78
- );
79
- (0, _react.useEffect)(function () {
80
- var _api$analytics, _api$analytics2;
81
- if (!(api !== null && api !== void 0 && (_api$analytics = api.analytics) !== null && _api$analytics !== void 0 && (_api$analytics = _api$analytics.actions) !== null && _api$analytics !== void 0 && _api$analytics.fireAnalyticsEvent)) {
82
- return;
83
- }
84
- var stopTime = performance.now();
85
- var time = stopTime - startTime;
86
- api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.fireAnalyticsEvent({
87
- action: _analytics.ACTION.RENDERED,
88
- actionSubject: _analytics.ACTION_SUBJECT.TYPEAHEAD,
89
- eventType: _analytics.EVENT_TYPE.OPERATIONAL,
90
- attributes: {
91
- time: time,
92
- items: items.length,
93
- initial: isEmptyQuery
94
- }
95
- });
96
- }, [startTime, items, isEmptyQuery,
97
- // In case the current triggerHandler changes
98
- // e.g: Inserting a mention using the quick insert
99
- // we need to send the event again
100
- // eslint-disable-next-line react-hooks/exhaustive-deps
101
- triggerHandler, api]);
102
-
103
- // useEffect(() => {
104
- // if (!api?.analytics?.actions?.fireAnalyticsEvent) {
105
- // return;
106
- // }
107
-
108
- // api?.analytics?.actions?.fireAnalyticsEvent({
109
- // action: ACTION.VIEWED,
110
- // actionSubject: ACTION_SUBJECT.TYPEAHEAD_ITEM,
111
- // eventType: EVENT_TYPE.OPERATIONAL,
112
- // attributes: {
113
- // index: selectedIndex,
114
- // items: items.length,
115
- // },
116
- // });
117
- // }, [
118
- // items,
119
- // api,
120
- // selectedIndex,
121
- // // In case the current triggerHandler changes
122
- // // e.g: Inserting a mention using the quick insert
123
- // // we need to send the event again
124
- // // eslint-disable-next-line react-hooks/exhaustive-deps
125
- // triggerHandler,
126
- // ]);
127
-
128
- var _useState = (0, _react.useState)(defaultMenuHeight),
129
- _useState2 = (0, _slicedToArray2.default)(_useState, 2),
130
- fitHeight = _useState2[0],
131
- setFitHeight = _useState2[1];
132
- var getFitHeight = (0, _react.useCallback)(function () {
133
- if (!anchorElement || !popupsMountPoint) {
134
- return;
135
- }
136
- var target = anchorElement;
137
- var _target$getBoundingCl = target.getBoundingClientRect(),
138
- targetTop = _target$getBoundingCl.top,
139
- targetHeight = _target$getBoundingCl.height;
140
- var boundariesElement = popupsBoundariesElement || document.body;
141
- var _boundariesElement$ge = boundariesElement.getBoundingClientRect(),
142
- boundariesHeight = _boundariesElement$ge.height,
143
- boundariesTop = _boundariesElement$ge.top;
144
-
145
- // Calculating the space above and space below our decoration
146
- var spaceAbove = targetTop - (boundariesTop - boundariesElement.scrollTop);
147
- var spaceBelow = boundariesTop + boundariesHeight - (targetTop + targetHeight);
148
-
149
- // Keep default height if more than enough space
150
- if (spaceBelow >= defaultMenuHeight) {
151
- return setFitHeight(defaultMenuHeight);
152
- }
153
-
154
- // Determines whether typeahead will fit above or below decoration
155
- // and return the space available.
156
- var newFitHeight = spaceBelow >= spaceAbove ? spaceBelow : spaceAbove;
157
-
158
- // Each typeahead item has some padding
159
- // We want to leave some space at the top so first item
160
- // is not partially cropped
161
- var fitHeightWithSpace = newFitHeight - ITEM_PADDING * 2;
162
-
163
- // Ensure typeahead height is max its default height
164
- var minFitHeight = Math.min(defaultMenuHeight, fitHeightWithSpace);
165
- return setFitHeight(minFitHeight);
166
- }, [anchorElement, defaultMenuHeight, popupsBoundariesElement, popupsMountPoint]);
167
- var getFitHeightDebounced = (0, _rafSchd.default)(getFitHeight);
168
- (0, _react.useLayoutEffect)(function () {
169
- // Ignored via go/ees005
170
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
171
- var scrollableElement = popupsScrollableElement || (0, _ui.findOverflowScrollParent)(anchorElement);
172
- getFitHeight();
173
- // Ignored via go/ees005
174
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
175
- window.addEventListener('resize', getFitHeightDebounced);
176
- if (scrollableElement) {
177
- // Ignored via go/ees005
178
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
179
- scrollableElement.addEventListener('scroll', getFitHeightDebounced);
180
- }
181
- return function () {
182
- // Ignored via go/ees005
183
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
184
- window.removeEventListener('resize', getFitHeightDebounced);
185
- if (scrollableElement) {
186
- // Ignored via go/ees005
187
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
188
- scrollableElement.removeEventListener('scroll', getFitHeightDebounced);
189
- }
190
- };
191
- }, [anchorElement, popupsScrollableElement, getFitHeightDebounced, getFitHeight]);
192
- (0, _react.useLayoutEffect)(function () {
193
- var focusOut = function focusOut(event) {
194
- var _window$getSelection;
195
- var relatedTarget = event.relatedTarget;
196
-
197
- // Given the user is changing the focus
198
- // When the target is inside the TypeAhead Popup
199
- // Then the popup should stay open
200
- if (relatedTarget instanceof HTMLElement && relatedTarget.closest && (relatedTarget.closest(".".concat(_constants.TYPE_AHEAD_POPUP_CONTENT_CLASS)) || relatedTarget.closest("[data-type-ahead=\"".concat(_constants.TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE, "\"]")))) {
201
- return;
202
- }
203
-
204
- // Handles cases like emoji and @ typeaheads that open new typeaheads
205
- var isTextSelected = ((_window$getSelection = window.getSelection()) === null || _window$getSelection === void 0 ? void 0 : _window$getSelection.type) === 'Range';
206
- var innerEditor = anchorElement.closest('.extension-editable-area');
207
- if (innerEditor) {
208
- // When there is no related target, we default to not closing the popup
209
- var newFocusInsideCurrentEditor = !relatedTarget;
210
- if (relatedTarget instanceof HTMLElement) {
211
- // check if the new focus is inside inner editor, keep popup opens
212
- newFocusInsideCurrentEditor = innerEditor.contains(relatedTarget);
213
- }
214
- if (!isTextSelected && newFocusInsideCurrentEditor) {
215
- return;
216
- }
217
- } else {
218
- // if the current focus in outer editor, keep the existing behaviour, do not close the pop up if text is not selected
219
- if (!isTextSelected) {
220
- return;
221
- }
222
- }
223
- cancel({
224
- addPrefixTrigger: true,
225
- setSelectionAt: _constants.CloseSelectionOptions.AFTER_TEXT_INSERTED,
226
- forceFocusOnEditor: false
227
- });
228
- };
229
- var element = ref.current;
230
- // Ignored via go/ees005
231
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
232
- element === null || element === void 0 || element.addEventListener('focusout', focusOut);
233
- return function () {
234
- // Ignored via go/ees005
235
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
236
- element === null || element === void 0 || element.removeEventListener('focusout', focusOut);
237
- };
238
- }, [ref, cancel, anchorElement]);
239
-
240
- // TODO: ED-17443 - When you press escape on typeahead panel, it should remove focus and close the panel
241
- // This is the expected keyboard behaviour advised by the Accessibility team
242
- (0, _react.useLayoutEffect)(function () {
243
- var escape = function escape(event) {
244
- if (event.key === 'Escape') {
245
- cancel({
246
- addPrefixTrigger: true,
247
- setSelectionAt: _constants.CloseSelectionOptions.AFTER_TEXT_INSERTED,
248
- forceFocusOnEditor: true
249
- });
250
- }
251
- };
252
- var element = ref.current;
253
- // Ignored via go/ees005
254
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
255
- element === null || element === void 0 || element.addEventListener('keydown', escape);
256
- return function () {
257
- // Ignored via go/ees005
258
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
259
- element === null || element === void 0 || element.removeEventListener('keydown', escape);
260
- };
261
- }, [ref, cancel]);
262
- var handleViewAllItemsClick = (0, _react.useCallback)(function () {
263
- var _api$contextPanel;
264
- var showContextPanel = api === null || api === void 0 || (_api$contextPanel = api.contextPanel) === null || _api$contextPanel === void 0 || (_api$contextPanel = _api$contextPanel.actions) === null || _api$contextPanel === void 0 ? void 0 : _api$contextPanel.showPanel;
265
- if (!showContextPanel || !items) {
266
- return;
267
- }
268
-
269
- // Opens main editor controls side panel
270
- showContextPanel({
271
- id: 'editor-element-insert-sidebar-panel',
272
- headerComponentElements: {
273
- headerLabel: _messages.elementInsertSidePanel.title,
274
- HeaderIcon: function HeaderIcon() {
275
- return (0, _react2.jsx)(_add.default, {
276
- label: formatMessage(_messages.elementInsertSidePanel.title)
277
- });
278
- }
279
- },
280
- BodyComponent: function BodyComponent() {
281
- return (0, _react2.jsx)(_editorElementBrowser.SideInsertPanel, {
282
- items: items,
283
- onItemInsert: onItemInsert
284
- });
285
- }
286
- }, 'push', INSERT_PANEL_WIDTH);
287
-
288
- // Closes typeahead
289
- cancel({
290
- addPrefixTrigger: true,
291
- setSelectionAt: _constants.CloseSelectionOptions.AFTER_TEXT_INSERTED,
292
- forceFocusOnEditor: true
293
- });
294
- }, [api, cancel, formatMessage, items, onItemInsert]);
295
- return (0, _react2.jsx)(_ui.Popup, {
296
- zIndex: _editorSharedStyles.akEditorFloatingDialogZIndex,
297
- target: anchorElement,
298
- mountTo: popupsMountPoint,
299
- boundariesElement: popupsBoundariesElement,
300
- scrollableElement: popupsScrollableElement,
301
- fitHeight: fitHeight,
302
- fitWidth: 280,
303
- offset: OFFSET,
304
- ariaLabel: null,
305
- preventOverflow: true
306
- }, (0, _react2.jsx)("div", {
307
- css: [typeAheadContent],
308
- tabIndex: (0, _platformFeatureFlags.fg)('platform_editor_a11y_fix_typeahead_tabindex') ? undefined : 0
309
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
310
- ,
311
- className: _constants.TYPE_AHEAD_POPUP_CONTENT_CLASS,
312
- ref: ref
313
- }, errorInfo ? (0, _react2.jsx)(_TypeAheadErrorFallback.TypeAheadErrorFallback, null) : (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_editorElementBrowser.QuickInsertPanel, {
314
- items: items,
315
- onItemInsert: onItemInsert,
316
- query: query,
317
- setSelectedItem: setSelectedItem,
318
- onViewAllItemsClick: Boolean(api === null || api === void 0 ? void 0 : api.contextPanel) ? handleViewAllItemsClick : undefined
319
- }))));
320
- });
321
- TypeAheadPopup.displayName = 'TypeAheadPopup';
@@ -1,76 +0,0 @@
1
- import React from 'react';
2
- import { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
3
- import { updateSelectedIndex } from '../../pm-plugins/commands/update-selected-index';
4
- import { useItemInsert } from '../hooks/use-item-insert';
5
- import { TypeAheadPopup as TypeAheadPopupModern } from './TypeAheadPopup';
6
- export const TypeAheadMenu = /*#__PURE__*/React.memo(({
7
- editorView,
8
- popupMountRef,
9
- typeAheadState,
10
- api
11
- }) => {
12
- var _popupMountRef$curren, _popupMountRef$curren2, _popupMountRef$curren3;
13
- const isOpen = typeAheadState.decorationSet.find().length > 0;
14
- const {
15
- triggerHandler,
16
- items,
17
- errorInfo,
18
- decorationElement,
19
- decorationSet,
20
- query
21
- } = typeAheadState;
22
- const [onItemInsert, onTextInsert] = useItemInsert(
23
- // Ignored via go/ees005
24
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
25
- triggerHandler, editorView, items, api);
26
- const setSelectedItem = React.useCallback(({
27
- index: nextIndex
28
- }) => {
29
- queueMicrotask(() => {
30
- updateSelectedIndex(nextIndex, api)(editorView.state, editorView.dispatch);
31
- });
32
- }, [editorView, api]);
33
- const insertItem = React.useCallback((mode = SelectItemMode.SELECTED, index) => {
34
- queueMicrotask(() => {
35
- onItemInsert({
36
- mode,
37
- index,
38
- query
39
- });
40
- });
41
- }, [onItemInsert, query]);
42
- const cancel = React.useCallback(({
43
- setSelectionAt,
44
- addPrefixTrigger,
45
- forceFocusOnEditor
46
- }) => {
47
- const fullQuery = addPrefixTrigger ? `${triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.trigger}${query}` : query;
48
- onTextInsert({
49
- forceFocusOnEditor,
50
- setSelectionAt,
51
- text: fullQuery
52
- });
53
- }, [triggerHandler, onTextInsert, query]);
54
- if (!isOpen || !triggerHandler || !(decorationElement instanceof HTMLElement) || items.length === 0 && !errorInfo) {
55
- return null;
56
- }
57
- return /*#__PURE__*/React.createElement(TypeAheadPopupModern, {
58
- editorView: editorView,
59
- popupsMountPoint: (_popupMountRef$curren = popupMountRef.current) === null || _popupMountRef$curren === void 0 ? void 0 : _popupMountRef$curren.popupsMountPoint,
60
- popupsBoundariesElement: (_popupMountRef$curren2 = popupMountRef.current) === null || _popupMountRef$curren2 === void 0 ? void 0 : _popupMountRef$curren2.popupsBoundariesElement,
61
- popupsScrollableElement: (_popupMountRef$curren3 = popupMountRef.current) === null || _popupMountRef$curren3 === void 0 ? void 0 : _popupMountRef$curren3.popupsScrollableElement,
62
- anchorElement: decorationElement,
63
- triggerHandler: triggerHandler,
64
- items: items,
65
- errorInfo: errorInfo
66
- // selectedIndex={selectedIndex}
67
- ,
68
- setSelectedItem: setSelectedItem,
69
- onItemInsert: insertItem,
70
- decorationSet: decorationSet,
71
- isEmptyQuery: !query,
72
- query: query,
73
- cancel: cancel,
74
- api: api
75
- });
76
- });