UNPKG

@atlaskit/editor-plugin-quick-insert

Version:

Quick insert plugin for @atlaskit/editor-core

155 lines (154 loc) • 7.57 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'; import { normalizeQuickInsertMatchResult } from '../normalizeQuickInsertMatchResult'; 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 getChildren = (components, parentKey, surfaceContext) => components.filter(component => { var _component$parents, _component$isHidden; return ((_component$parents = component.parents) === null || _component$parents === void 0 ? void 0 : _component$parents.some(parent => parent.key === parentKey)) && ((_component$isHidden = component.isHidden) === null || _component$isHidden === void 0 ? void 0 : _component$isHidden.call(component, { surfaceContext })) !== true; }); 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, surfaceContext) => getChildren(components, parentKey, surfaceContext).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, surfaceContext); }); /** * Builds the Element Browser's view of the resolved Quick Insert registry. * The caller provides only components rooted at the Quick Insert menu surface. */ export const createRegistryElementBrowserModel = (components, { footerKey, overflowKeys, recommendedRegistrations = [], recommendedSectionKey, rootKey, surfaceContext }) => { const excludedKeys = new Set([footerKey, recommendedSectionKey, ...overflowKeys]); const visibleComponents = components.filter(component => !excludedKeys.has(component.key)); const sections = getChildren(visibleComponents, rootKey, surfaceContext).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, surfaceContext).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); const recommendedItems = [...new Set(recommendedRegistrations.map(({ key }) => key))].flatMap(key => { var _itemByKey$get; return (_itemByKey$get = itemByKey.get(key)) !== null && _itemByKey$get !== void 0 ? _itemByKey$get : []; }); return { fallbackItems: fallbackItems.length > 0 ? fallbackItems : undefined, items, recommendedItems, sections }; }; /** * Lays out Recommended so every row is full: wide tiles take half a row and regular tiles a third. * An odd count of three or more ends with a row of three regular tiles; every other tile is wide. */ export const getRecommendedTileSize = (index, count) => count >= 3 && count % 2 === 1 && index >= count - 3 ? 'regular' : 'wide'; export const getInitialRegistryElementBrowserSection = (model, requestedSection) => model.sections.some(section => section.key === requestedSection) ? requestedSection : undefined; export const getRegistryElementBrowserItems = ({ formatMessage, model, query, section }) => { const withDescription = item => { var _createQuickInsertMat; return { ...item, description: (_createQuickInsertMat = createQuickInsertMatcher.getDescription) === null || _createQuickInsertMat === void 0 ? void 0 : _createQuickInsertMat.call(createQuickInsertMatcher, item.registration.match, formatMessage) }; }; if (section === undefined && query === '') { const recommendedKeys = new Set(model.recommendedItems.map(({ registration }) => registration.key)); return { items: model.items.filter(({ registration }) => !recommendedKeys.has(registration.key)).map(withDescription), recommendedItems: model.recommendedItems.map(withDescription) }; } const normalizedQuery = query.trim(); const itemsWithDescriptions = (section ? model.items.filter(item => item.sectionKeys.includes(section)) : model.items).map(withDescription); if (!normalizedQuery) { return { items: itemsWithDescriptions, recommendedItems: [] }; } const matches = 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, itemKey: item.registration.key, query: normalizedQuery }); return result ? [{ ...item, ...normalizeQuickInsertMatchResult(result) }] : []; }); const prioritized = matches.filter(({ priorityGroup }) => priorityGroup !== undefined); const unprioritized = matches.filter(({ priorityGroup }) => priorityGroup === undefined); return { items: [...prioritized.sort((left, right) => { var _right$priorityGroup, _left$priorityGroup; return ((_right$priorityGroup = right.priorityGroup) !== null && _right$priorityGroup !== void 0 ? _right$priorityGroup : 0) - ((_left$priorityGroup = left.priorityGroup) !== null && _left$priorityGroup !== void 0 ? _left$priorityGroup : 0) || left.score - right.score || compareRanks(left.ranks, right.ranks) || left.registration.key.localeCompare(right.registration.key); }), ...unprioritized.sort((left, right) => { var _left$ranks$, _right$ranks$; return ((_left$ranks$ = left.ranks[0]) !== null && _left$ranks$ !== void 0 ? _left$ranks$ : 0) - ((_right$ranks$ = right.ranks[0]) !== null && _right$ranks$ !== void 0 ? _right$ranks$ : 0) || left.score - right.score || compareRanks(left.ranks, right.ranks) || left.registration.key.localeCompare(right.registration.key); })], recommendedItems: [] }; };