UNPKG

@atlaskit/editor-plugin-quick-insert

Version:

Quick insert plugin for @atlaskit/editor-core

216 lines • 10.3 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _toArray from "@babel/runtime/helpers/toArray"; var _excluded = ["rows", "selectableItems", "selectedItemIndex", "activeItemKey", "selectionSource"]; function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useIntl } from 'react-intl'; import { INPUT_METHOD } from '@atlaskit/editor-common/analytics/types/enums'; import { toolbarInsertBlockMessages } from '@atlaskit/editor-common/messages/insert-block'; import { QuickInsertProvider } from '@atlaskit/editor-common/quick-insert/provider'; import { useRegisteredMenuContext } from '@atlaskit/editor-common/registered-menu/context'; import { REGISTERED_MENU_SURFACE_CONTEXT } from '@atlaskit/editor-common/registered-menu/surface-context'; import { useRegisteredMenu } from '@atlaskit/editor-common/registered-menu/use-registered-menu'; import { isSectionOverflowItemKey } from '@atlaskit/editor-common/type-ahead-is-section-overflow-item-key'; import { typeAheadListMessages } from '@atlaskit/editor-common/type-ahead/messages'; import MenuGroup from '@atlaskit/menu/menu-group'; import { getQuickInsertMenuModel } from './get-quick-insert-menu-model'; import { getQuickInsertMenuItemId } from './getQuickInsertMenuItemId'; import { RegisteredQuickInsertMenuItem } from './RegisteredQuickInsertMenuItem'; import { selectQuickInsertCategoryItems } from './selectQuickInsertCategoryItems'; import { ToolbarQuickInsertMenu } from './ToolbarQuickInsertMenu'; import { TypeAheadQuickInsertMenu } from './TypeAheadQuickInsertMenu'; import { useQuickInsertSearchAnalytics } from './useQuickInsertSearchAnalytics'; var DEFAULT_MENU_MAX_HEIGHT = 480; var isImeEnter = function isImeEnter(event) { return event.isComposing || event.keyCode === 229; }; var QuickInsertMenuRoot = function QuickInsertMenuRoot(_ref) { var _surfaceContext$get, _registeredMenu$maxHe; var emptyStateHandler = _ref.emptyStateHandler, fireAnalyticsEvent = _ref.fireAnalyticsEvent, getItemRank = _ref.getItemRank, getRecommendedItems = _ref.getRecommendedItems; var registeredMenu = useRegisteredMenuContext(); var _registeredMenu$query = registeredMenu.query, query = _registeredMenu$query === void 0 ? '' : _registeredMenu$query, selectFromHost = registeredMenu.select, surfaceContext = registeredMenu.surfaceContext; var surface = (_surfaceContext$get = surfaceContext.get(REGISTERED_MENU_SURFACE_CONTEXT)) === null || _surfaceContext$get === void 0 ? void 0 : _surfaceContext$get.surface; if (!selectFromHost || !surface || surface === 'element-browser') { throw new Error('QuickInsertMenuRoot requires a selection action and registered menu surface'); } var _useIntl = useIntl(), formatMessage = _useIntl.formatMessage; var components = registeredMenu.components, runtimeItemRank = registeredMenu.getItemRank, rootComponent = registeredMenu.rootComponent; var model = useMemo(function () { return getQuickInsertMenuModel({ components: components, formatMessage: formatMessage, getItemRank: runtimeItemRank !== null && runtimeItemRank !== void 0 ? runtimeItemRank : getItemRank, getRecommendedItems: getRecommendedItems, query: query, rootComponent: rootComponent, selectCategoryItems: components.some(function (_ref2) { var key = _ref2.key; return isSectionOverflowItemKey(key); }) ? selectQuickInsertCategoryItems : undefined, surfaceContext: surfaceContext }); }, [components, formatMessage, getItemRank, getRecommendedItems, query, rootComponent, runtimeItemRank, surfaceContext]); var resultCount = useMemo(function () { return model.sections.reduce(function (count, _ref3) { var _ref4 = _toArray(_ref3), items = _arrayLikeToArray(_ref4).slice(1); return count + items.filter(function (_ref5) { var key = _ref5.key; return !isSectionOverflowItemKey(key); }).length; }, 0); }, [model.sections]); var flushSearchAnalytics = useQuickInsertSearchAnalytics({ surface: surface, fireAnalyticsEvent: fireAnalyticsEvent, query: query, resultCount: resultCount }); var selectItem = useCallback(function (selection) { flushSearchAnalytics(); selectFromHost(function (insert) { return selection({ insert: insert, source: surface === 'toolbar' ? INPUT_METHOD.INSERT_MENU : INPUT_METHOD.QUICK_INSERT }); }); }, [flushSearchAnalytics, selectFromHost, surface]); var menuContextValue = useMemo(function () { return { editorView: registeredMenu.editorView, isOffline: registeredMenu.isOffline, popupsMountPoint: registeredMenu.portalMountPoint, select: selectItem, surfaceContext: registeredMenu.surfaceContext }; }, [registeredMenu.editorView, registeredMenu.isOffline, registeredMenu.portalMountPoint, registeredMenu.surfaceContext, selectItem]); var listLabel = formatMessage(surface === 'typeahead' ? typeAheadListMessages.quickInsertInputLabel : toolbarInsertBlockMessages.insertMenu); var _useRegisteredMenu = useRegisteredMenu({ model: model, resetKey: query }), rows = _useRegisteredMenu.rows, selectableItems = _useRegisteredMenu.selectableItems, selectedItemIndex = _useRegisteredMenu.selectedItemIndex, activeItemKey = _useRegisteredMenu.activeItemKey, selectionSource = _useRegisteredMenu.selectionSource, listEvents = _objectWithoutProperties(_useRegisteredMenu, _excluded); var listId = useId(); var _useState = useState({ startIndex: -1, stopIndex: -1 }), _useState2 = _slicedToArray(_useState, 2), renderedItems = _useState2[0], setRenderedItems = _useState2[1]; var menuRef = useRef(null); var maxHeight = (_registeredMenu$maxHe = registeredMenu.maxHeight) !== null && _registeredMenu$maxHe !== void 0 ? _registeredMenu$maxHe : DEFAULT_MENU_MAX_HEIGHT; var itemCount = selectableItems.length + (model.footer ? 1 : 0); var activeItemId = selectedItemIndex >= 0 && selectedItemIndex < itemCount ? getQuickInsertMenuItemId(listId, selectedItemIndex) : undefined; var isActiveItemMounted = selectedItemIndex >= 0 && selectedItemIndex < itemCount && (selectedItemIndex >= renderedItems.startIndex && selectedItemIndex <= renderedItems.stopIndex || Boolean(model.footer) && selectedItemIndex === itemCount - 1); var selectActiveItem = useCallback(function () { if (isActiveItemMounted && activeItemId) { var _menuRef$current; (_menuRef$current = menuRef.current) === null || _menuRef$current === void 0 || (_menuRef$current = _menuRef$current.ownerDocument.getElementById(activeItemId)) === null || _menuRef$current === void 0 || _menuRef$current.click(); } }, [activeItemId, isActiveItemMounted]); var onMenuKeyDown = useCallback(function (event) { if (event.key === 'ArrowDown') { listEvents.selectNext(); return true; } if (event.key === 'ArrowUp') { listEvents.selectPrevious(); return true; } if (event.key === 'Enter') { if (isImeEnter(event)) { return false; } selectActiveItem(); return true; } return false; }, [listEvents.selectNext, listEvents.selectPrevious, selectActiveItem]); var containsTarget = useCallback(function (target) { var _menuRef$current2; return Boolean((_menuRef$current2 = menuRef.current) === null || _menuRef$current2 === void 0 ? void 0 : _menuRef$current2.contains(target)); }, []); var interaction = useMemo(function () { return { activeDescendantId: isActiveItemMounted ? activeItemId : undefined, containsTarget: containsTarget, expanded: itemCount > 0, label: listLabel, listId: listId, onKeyDown: onMenuKeyDown, onClose: flushSearchAnalytics, optionCount: itemCount, selectNext: listEvents.selectNext, selectPrevious: listEvents.selectPrevious }; }, [activeItemId, containsTarget, flushSearchAnalytics, isActiveItemMounted, itemCount, listId, listLabel, listEvents.selectNext, listEvents.selectPrevious, onMenuKeyDown]); useLayoutEffect(function () { if (!model.root) { return; } return registeredMenu.registerInteraction(interaction); }, [model.root, interaction, registeredMenu.registerInteraction]); if (!model.root) { return null; } return /*#__PURE__*/React.createElement(QuickInsertProvider, { value: menuContextValue }, /*#__PURE__*/React.createElement("div", { ref: menuRef }, /*#__PURE__*/React.createElement(MenuGroup, null, surface === 'typeahead' ? /*#__PURE__*/React.createElement(TypeAheadQuickInsertMenu, { Item: RegisteredQuickInsertMenuItem, activeItemKey: activeItemKey, hasScrollPadding: true, itemCount: itemCount, listId: listId, listLabel: listLabel, maxHeight: maxHeight, model: model, onItemBlur: listEvents.onItemBlur, onItemFocus: listEvents.onItemFocus, onItemHover: listEvents.onItemHover, onItemLeave: listEvents.onItemLeave, onItemVisibilityChange: listEvents.onItemVisibilityChange, onRenderedItemsChange: setRenderedItems, query: query, rows: rows, selectedItemIndex: selectedItemIndex, selectionSource: selectionSource }) : /*#__PURE__*/React.createElement(ToolbarQuickInsertMenu, { Item: RegisteredQuickInsertMenuItem, activePreviewItemKey: activeItemKey, emptyStateHandler: emptyStateHandler, itemCount: itemCount, listId: listId, listLabel: listLabel, maxHeight: maxHeight, model: model, onItemBlur: listEvents.onItemBlur, onItemFocus: listEvents.onItemFocus, onItemHover: listEvents.onItemHover, onItemLeave: listEvents.onItemLeave, onItemVisibilityChange: listEvents.onItemVisibilityChange, onRenderedItemsChange: setRenderedItems, query: query, rows: rows, selectedItemIndex: selectedItemIndex, selectionSource: selectionSource })))); }; export default QuickInsertMenuRoot;