UNPKG

@atlaskit/editor-plugin-quick-insert

Version:

Quick insert plugin for @atlaskit/editor-core

111 lines (110 loc) • 5.33 kB
import { createQuickInsertMatcher } from '@atlaskit/editor-common/quick-insert/create-quick-insert-matcher'; import { ASK_ROVO_MENU_ITEM } from '@atlaskit/editor-common/quick-insert/keys'; const compareRanks = (left, right) => { for (let index = 0; index < Math.max(left.length, right.length); index++) { var _left$index, _right$index; const difference = ((_left$index = left[index]) !== null && _left$index !== void 0 ? _left$index : 0) - ((_right$index = right[index]) !== null && _right$index !== void 0 ? _right$index : 0); if (difference !== 0) { return difference; } } return 0; }; const isVisible = registration => { var _registration$isHidde; return ((_registration$isHidde = registration.isHidden) === null || _registration$isHidde === void 0 ? void 0 : _registration$isHidde.call(registration)) !== true; }; const getChildren = (components, parentKey) => components.filter(component => { var _component$parents; return isVisible(component) && ((_component$parents = component.parents) === null || _component$parents === void 0 ? void 0 : _component$parents.some(parent => parent.key === parentKey)); }); const getParentRank = (registration, parentKey) => { var _registration$parents, _registration$parents2, _registration$parents3; return (_registration$parents = (_registration$parents2 = registration.parents) === null || _registration$parents2 === void 0 ? void 0 : (_registration$parents3 = _registration$parents2.find(parent => parent.key === parentKey)) === null || _registration$parents3 === void 0 ? void 0 : _registration$parents3.rank) !== null && _registration$parents !== void 0 ? _registration$parents : Number.MAX_SAFE_INTEGER; }; const getDescendantItems = (components, parentKey, ancestorRanks, sectionKey) => getChildren(components, parentKey).flatMap(component => { const ranks = [...ancestorRanks, getParentRank(component, parentKey)]; if (component.type === 'menu-item') { return component.component ? [{ ranks, registration: component, sectionKeys: [sectionKey] }] : []; } return getDescendantItems(components, component.key, ranks, sectionKey); }); /** * Builds the Element Browser's immutable open-time view of the Quick Insert registry. * The caller provides only components rooted at the Quick Insert menu surface. */ export const createRegistryElementBrowserModel = (components, { footerKey, overflowKeys, recommendedSectionKey, rootKey }) => { const excludedKeys = new Set([footerKey, recommendedSectionKey, ...overflowKeys]); const visibleComponents = components.filter(component => isVisible(component) && !excludedKeys.has(component.key)); const sections = getChildren(visibleComponents, rootKey).filter(component => component.type === 'menu-section').map(section => ({ key: section.key, rank: getParentRank(section, rootKey) })).sort((left, right) => left.rank - right.rank); const itemByKey = new Map(); sections.forEach(section => { getDescendantItems(visibleComponents, section.key, [section.rank], section.key).forEach(item => { const existing = itemByKey.get(item.registration.key); if (!existing) { itemByKey.set(item.registration.key, item); return; } const sectionKeys = [...new Set([...existing.sectionKeys, ...item.sectionKeys])]; itemByKey.set(item.registration.key, compareRanks(item.ranks, existing.ranks) < 0 ? { ...item, sectionKeys } : { ...existing, sectionKeys }); }); }); const items = [...itemByKey.values()].sort((left, right) => compareRanks(left.ranks, right.ranks)); const fallbackItems = items.filter(({ registration }) => registration.key === ASK_ROVO_MENU_ITEM.key); return { fallbackItems: fallbackItems.length > 0 ? fallbackItems : undefined, items, sections }; }; export const getInitialRegistryElementBrowserSection = (model, requestedSection) => model.sections.some(section => section.key === requestedSection) ? requestedSection : undefined; export const getRegistryElementBrowserItems = ({ formatMessage, model, query, section }) => { const normalizedQuery = query.trim(); const items = section ? model.items.filter(item => item.sectionKeys.includes(section)) : model.items; const itemsWithDescriptions = items.map(item => { var _createQuickInsertMat; return { ...item, description: (_createQuickInsertMat = createQuickInsertMatcher.getDescription) === null || _createQuickInsertMat === void 0 ? void 0 : _createQuickInsertMat.call(createQuickInsertMatcher, item.registration.match, formatMessage) }; }); if (!normalizedQuery) { return itemsWithDescriptions; } return itemsWithDescriptions.flatMap(item => { var _item$registration$ma, _item$registration; const result = (_item$registration$ma = (_item$registration = item.registration).match) === null || _item$registration$ma === void 0 ? void 0 : _item$registration$ma.call(_item$registration, { formatMessage, query: normalizedQuery }); return result ? [{ ...item, score: Math.min(1, Math.max(0, result.score)) }] : []; }).sort((left, right) => left.score - right.score || compareRanks(left.ranks, right.ranks) || left.registration.key.localeCompare(right.registration.key)); };