@atlaskit/editor-plugin-quick-insert
Version:
Quick insert plugin for @atlaskit/editor-core
111 lines (110 loc) • 5.33 kB
JavaScript
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));
};