UNPKG

@atlaskit/editor-plugin-type-ahead

Version:

Type-ahead plugin for @atlaskit/editor-core

207 lines (206 loc) 5.26 kB
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { SelectItemMode, TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead'; import { closeTypeAhead } from './commands/close-type-ahead'; import { insertTypeAheadItem } from './commands/insert-type-ahead-item'; import { openTypeAheadAtCursor } from './commands/open-typeahead-at-cursor'; import { updateQuery } from './commands/update-query'; import { findHandler, getTypeAheadHandler, getTypeAheadQuery, isTypeAheadOpen } from './utils'; const open = ({ editorView }) => itemType => inputMethod => { const { state } = editorView; const handler = findHandler(itemType, state); if (!handler) { return false; } const { tr } = state; openTypeAheadAtCursor({ triggerHandler: handler, inputMethod })({ tr }); editorView.dispatch(tr); return true; }; const defaultCloseOptions = { insertCurrentQueryAsRawText: false }; const close = ({ editorView }) => (options = defaultCloseOptions) => { const { state } = editorView; const currentQuery = getTypeAheadQuery(editorView.state); let tr = state.tr; if (options.attachCommand) { const fakeDispatch = customTr => { tr = customTr; }; options.attachCommand(state, fakeDispatch); } closeTypeAhead(tr); if (options.insertCurrentQueryAsRawText && currentQuery && currentQuery.length > 0) { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const handler = getTypeAheadHandler(state); const text = handler.trigger.concat(currentQuery); tr.replaceSelectionWith(state.schema.text(text)); } editorView.dispatch(tr); if (!editorView.hasFocus()) { editorView.focus(); } return true; }; const search = ({ editorView }) => itemType => (query = '') => { const { state } = editorView; const handler = findHandler(itemType, state); if (!handler) { throw new Error(`Handler not found, did you load the ${itemType} plugin properly`); } open({ editorView })(itemType)(INPUT_METHOD.KEYBOARD); updateQuery(query)(editorView.state, editorView.dispatch); const lastQuery = { current: query }; const last = handler.getItems({ query, editorState: state }).then(items => { if (!handler.forceSelect) { return items; } const forceSelectedItem = handler.forceSelect({ items, query, editorState: state }); if (!forceSelectedItem) { return items; } insertTypeAheadItem(editorView)({ handler, item: forceSelectedItem, query, mode: SelectItemMode.SELECTED, sourceListItem: items }); }); const results = { last }; return { type: appendValue => { if (!appendValue) { return; } lastQuery.current += appendValue; updateQuery(lastQuery.current)(editorView.state, editorView.dispatch); const promise = handler.getItems({ query: lastQuery.current, editorState: state }); results.last = promise; return promise; }, result: () => results.last, close: close({ editorView }), insert: ({ index, mode }) => { return results.last.then(result => { const item = result ? result[index] : null; if (result && item) { insertTypeAheadItem(editorView)({ handler, item, query, mode: mode || SelectItemMode.SELECTED, sourceListItem: result }); } }); } }; }; const insertItem = ({ editorView }) => itemType => ({ contentItem, query, sourceListItem }) => { const { state } = editorView; const handler = findHandler(itemType, state); if (!handler) { return false; } insertTypeAheadItem(editorView)({ handler, item: contentItem, mode: SelectItemMode.SELECTED, query, sourceListItem }); return true; }; const isOpen = ({ editorView }) => () => { if (!isTypeAheadOpen(editorView.state)) { return false; } const handler = getTypeAheadHandler(editorView.state); if (!handler) { return false; } return handler; }; const currentQuery = ({ editorView }) => () => { return getTypeAheadQuery(editorView.state); }; /** * Please do not use it. Ping #help-editor and talk to the Lego team before use it. * * @private * @deprecated * */ export const createTypeAheadTools = editorView => { const props = { editorView }; return { isOpen: isOpen(props), currentQuery: currentQuery(props), close: close(props), openMention: open(props)(TypeAheadAvailableNodes.MENTION), searchMention: search(props)(TypeAheadAvailableNodes.MENTION), openQuickInsert: open(props)(TypeAheadAvailableNodes.QUICK_INSERT), searchQuickInsert: search(props)(TypeAheadAvailableNodes.QUICK_INSERT), openEmoji: open(props)(TypeAheadAvailableNodes.EMOJI), searchEmoji: search(props)(TypeAheadAvailableNodes.EMOJI), insertItemMention: insertItem(props)(TypeAheadAvailableNodes.MENTION), insertItemEmoji: insertItem(props)(TypeAheadAvailableNodes.EMOJI), insertItemQuickInsert: insertItem(props)(TypeAheadAvailableNodes.QUICK_INSERT) }; };