@atlaskit/editor-plugin-insert-block
Version:
Insert block plugin for @atlaskit/editor-core
284 lines (283 loc) • 12 kB
JavaScript
/* RegisteredInsertMenu.tsx generated by @compiled/babel-plugin v3.0.2 */
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import "./RegisteredInsertMenu.compiled.css";
import { ax, ix } from "@compiled/react/runtime";
import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useIntl } from 'react-intl';
import { getDocument } from '@atlaskit/browser-apis';
import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages/insert-block';
import { MENU } from '@atlaskit/editor-common/quick-insert/keys';
import { getQuickInsertMenuModel, getQuickInsertMenuRows, selectQuickInsertCategoryItems } from '@atlaskit/editor-common/quick-insert/registered-menu-model';
import { useQuickInsertSearchAnalytics } from '@atlaskit/editor-common/quick-insert/use-search-analytics';
import { isSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-is-section-overflow-item-key';
import { TYPE_AHEAD_SURFACE_CONTEXT } from '@atlaskit/editor-common/type-ahead-surface-context';
import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
import { Box } from '@atlaskit/primitives/compiled/box';
import Textfield from '@atlaskit/textfield/text-field';
import { RegisteredInsertMenuList } from './RegisteredInsertMenuList';
var DEFAULT_MENU_MAX_HEIGHT = 520;
var styles = {
menu: "_2rko1mok _1reo15vq _18m915vq _bfhk1bhr _16qs130s _1e0c1txw _2lx21bp4 _1bsb1edt",
search: "_18zrutpp _1o9zidpf _1q51utpp _85i5u2gc"
};
export var RegisteredInsertMenu = function RegisteredInsertMenu(_ref) {
var components = _ref.components,
emptyStateHandler = _ref.emptyStateHandler,
fireAnalyticsEvent = _ref.fireAnalyticsEvent,
getItemRank = _ref.getItemRank,
editorView = _ref.editorView,
isOffline = _ref.isOffline,
_ref$maxHeight = _ref.maxHeight,
maxHeight = _ref$maxHeight === void 0 ? DEFAULT_MENU_MAX_HEIGHT : _ref$maxHeight,
onClose = _ref.onClose,
onSelect = _ref.onSelect;
var menuStyle = {
maxHeight: maxHeight
};
var _useIntl = useIntl(),
formatMessage = _useIntl.formatMessage;
var listId = useId();
var _useState = useState(function () {
return Symbol('registered-insert-menu-open');
}),
_useState2 = _slicedToArray(_useState, 1),
menuOpenId = _useState2[0];
var _useState3 = useState(''),
_useState4 = _slicedToArray(_useState3, 2),
query = _useState4[0],
setQuery = _useState4[1];
var _useState5 = useState(0),
_useState6 = _slicedToArray(_useState5, 2),
selectedItemIndex = _useState6[0],
setSelectedItemIndex = _useState6[1];
var selectedItemIndexRef = useRef(selectedItemIndex);
var _useState7 = useState({
startIndex: -1,
stopIndex: -1
}),
_useState8 = _slicedToArray(_useState7, 2),
renderedItems = _useState8[0],
setRenderedItems = _useState8[1];
var searchRef = useRef(null);
useLayoutEffect(function () {
var _searchRef$current;
// Popup positions on the next frame; focusing must not scroll to its initial location.
(_searchRef$current = searchRef.current) === null || _searchRef$current === void 0 || _searchRef$current.focus({
preventScroll: true
});
}, []);
var surfaceContext = useMemo(function () {
return createSurfaceContext(TYPE_AHEAD_SURFACE_CONTEXT, {
menuOpenId: menuOpenId
});
}, [menuOpenId]);
var hasSectionOverflowItems = useMemo(function () {
return components.some(function (_ref2) {
var key = _ref2.key;
return isSectionOverflowItemKey(key);
});
}, [components]);
var model = useMemo(function () {
return getQuickInsertMenuModel({
components: components,
formatMessage: formatMessage,
getItemRank: getItemRank,
query: query,
rootComponent: MENU,
selectCategoryItems: hasSectionOverflowItems ? selectQuickInsertCategoryItems : undefined,
surfaceContext: surfaceContext
});
}, [components, formatMessage, getItemRank, hasSectionOverflowItems, query, surfaceContext]);
var _useState9 = useState(),
_useState0 = _slicedToArray(_useState9, 2),
previewActivation = _useState0[0],
setPreviewActivation = _useState0[1];
var activePreviewItemKey = (previewActivation === null || previewActivation === void 0 ? void 0 : previewActivation.model) === model ? previewActivation.itemKey : undefined;
var searchResultCount = useMemo(function () {
return model.sections.reduce(function (count, section) {
return count + section.filter(function (_ref3) {
var key = _ref3.key,
type = _ref3.type;
return type === 'menu-item' && !isSectionOverflowItemKey(key);
}).length;
}, 0);
}, [model.sections]);
var flushSearchAnalytics = useQuickInsertSearchAnalytics({
fireAnalyticsEvent: fireAnalyticsEvent,
query: query,
resultCount: searchResultCount,
surface: 'toolbar'
});
var closeWithAnalytics = useCallback(function () {
flushSearchAnalytics();
onClose();
}, [flushSearchAnalytics, onClose]);
var selectWithAnalytics = useCallback(function () {
flushSearchAnalytics();
onSelect();
}, [flushSearchAnalytics, onSelect]);
var selectableItems = useMemo(function () {
return getQuickInsertMenuRows(model).filter(function (row) {
return row.type === 'menu-item';
});
}, [model]);
var itemCount = selectableItems.length + (model.footer ? 1 : 0);
var selectableItemKeys = useMemo(function () {
return [].concat(_toConsumableArray(selectableItems), _toConsumableArray(model.footer ? [model.footer] : [])).map(function (_ref4) {
var key = _ref4.key;
return key;
}).join(',');
}, [model.footer, selectableItems]);
useLayoutEffect(function () {
var initialItemIndex = itemCount > 0 ? 0 : -1;
selectedItemIndexRef.current = initialItemIndex;
setSelectedItemIndex(initialItemIndex);
}, [itemCount, query, selectableItemKeys]);
useLayoutEffect(function () {
setPreviewActivation(undefined);
}, [model, query]);
var isActiveItemMounted = selectedItemIndex >= 0 && selectedItemIndex < itemCount && (selectedItemIndex >= renderedItems.startIndex && selectedItemIndex <= renderedItems.stopIndex || Boolean(model.footer) && selectedItemIndex === itemCount - 1);
var activeItemId = "".concat(listId, "-").concat(selectedItemIndex);
var setKeyboardPreview = useCallback(function (itemIndex) {
var item = selectableItems[itemIndex];
setPreviewActivation(item ? {
itemKey: item.key,
model: model,
source: 'keyboard'
} : undefined);
}, [model, selectableItems]);
var selectNextItem = useCallback(function () {
var currentIndex = selectedItemIndexRef.current;
var nextIndex = itemCount === 0 ? -1 : currentIndex < 0 ? 0 : (currentIndex + 1) % itemCount;
selectedItemIndexRef.current = nextIndex;
setSelectedItemIndex(nextIndex);
setKeyboardPreview(nextIndex);
}, [itemCount, setKeyboardPreview]);
var selectPreviousItem = useCallback(function () {
var currentIndex = selectedItemIndexRef.current;
var previousIndex = itemCount === 0 ? -1 : currentIndex <= 0 ? itemCount - 1 : currentIndex - 1;
selectedItemIndexRef.current = previousIndex;
setSelectedItemIndex(previousIndex);
setKeyboardPreview(previousIndex);
}, [itemCount, setKeyboardPreview]);
var onItemHover = useCallback(function (itemIndex, itemKey) {
selectedItemIndexRef.current = itemIndex;
setSelectedItemIndex(itemIndex);
setPreviewActivation(function (current) {
if ((current === null || current === void 0 ? void 0 : current.itemKey) === itemKey && (current === null || current === void 0 ? void 0 : current.model) === model && (current === null || current === void 0 ? void 0 : current.source) === 'pointer') {
return current;
}
return itemKey ? {
itemKey: itemKey,
model: model,
source: 'pointer'
} : undefined;
});
}, [model]);
var onItemFocus = useCallback(function (itemIndex, itemKey) {
selectedItemIndexRef.current = itemIndex;
setSelectedItemIndex(itemIndex);
setPreviewActivation(function (current) {
if ((current === null || current === void 0 ? void 0 : current.itemKey) === itemKey && (current === null || current === void 0 ? void 0 : current.model) === model) {
return current;
}
return itemKey ? {
itemKey: itemKey,
model: model,
source: 'keyboard'
} : undefined;
});
}, [model]);
var onItemLeave = useCallback(function (itemKey) {
setPreviewActivation(function (current) {
return (current === null || current === void 0 ? void 0 : current.source) === 'pointer' && current.itemKey === itemKey ? undefined : current;
});
}, []);
var onItemBlur = useCallback(function (itemKey) {
setPreviewActivation(function (current) {
return (current === null || current === void 0 ? void 0 : current.itemKey) === itemKey ? undefined : current;
});
}, []);
var onItemVisibilityChange = useCallback(function (itemKey, isVisible) {
if (!isVisible) {
setPreviewActivation(function (current) {
return (current === null || current === void 0 ? void 0 : current.source) === 'pointer' && current.itemKey === itemKey ? undefined : current;
});
}
}, []);
var selectActiveItem = useCallback(function () {
if (isActiveItemMounted) {
var _getDocument;
(_getDocument = getDocument()) === null || _getDocument === void 0 || (_getDocument = _getDocument.getElementById(activeItemId)) === null || _getDocument === void 0 || _getDocument.click();
}
}, [activeItemId, isActiveItemMounted]);
var onQueryChange = useCallback(function (event) {
setQuery(event.currentTarget.value);
}, []);
var onKeyDown = useCallback(function (event) {
if (event.key === 'Escape') {
event.preventDefault();
closeWithAnalytics();
return;
}
// The search field owns the composite's arrow-key and Enter behaviour. Other
// focusable controls, including consumer-provided empty-state content, need
// to retain their native keyboard behaviour.
if (event.target !== searchRef.current) {
return;
}
switch (event.key) {
case 'ArrowDown':
event.preventDefault();
selectNextItem();
break;
case 'ArrowUp':
event.preventDefault();
selectPreviousItem();
break;
case 'Enter':
event.preventDefault();
selectActiveItem();
break;
}
}, [closeWithAnalytics, selectActiveItem, selectNextItem, selectPreviousItem]);
return /*#__PURE__*/React.createElement(Box, {
"data-keyboard-navigation-independent": "",
testId: "registered-insert-menu",
onKeyDownCapture: onKeyDown,
xcss: styles.menu,
style: menuStyle
}, /*#__PURE__*/React.createElement(Box, {
xcss: styles.search
}, /*#__PURE__*/React.createElement(Textfield, {
"aria-activedescendant": isActiveItemMounted ? activeItemId : undefined,
"aria-controls": listId,
"aria-expanded": "true",
placeholder: "Search",
ref: searchRef,
role: "combobox",
value: query,
onChange: onQueryChange
})), /*#__PURE__*/React.createElement(RegisteredInsertMenuList, {
editorView: editorView,
emptyStateHandler: emptyStateHandler,
isOffline: isOffline,
listId: listId,
listLabel: formatMessage(messages.insertMenu),
maxHeight: maxHeight,
menuOpenId: menuOpenId,
model: model,
onClose: selectWithAnalytics,
onItemFocus: onItemFocus,
onItemHover: onItemHover,
onItemBlur: onItemBlur,
onItemLeave: onItemLeave,
onItemVisibilityChange: onItemVisibilityChange,
onRenderedItemsChange: setRenderedItems,
query: query,
selectedItemIndex: selectedItemIndex,
surfaceContext: surfaceContext,
activePreviewItemKey: activePreviewItemKey
}));
};