UNPKG

@atlaskit/editor-plugin-quick-insert

Version:

Quick insert plugin for @atlaskit/editor-core

151 lines 5.54 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import { ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics'; import { containsPopupWithNestedElement, Experience, EXPERIENCE_ID, ExperienceCheckDomMutation, ExperienceCheckTimeout, getPopupContainerFromEditorView } from '@atlaskit/editor-common/experiences'; import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { PluginKey } from '@atlaskit/editor-prosemirror/state'; var pluginKey = new PluginKey('quickInsertOpenExperience'); var TIMEOUT_DURATION = 1000; var START_METHOD = { QUICK_INSERT_BUTTON: 'quickInsertButton', TYPEAHEAD: 'typeahead' }; var ABORT_REASON = { USER_CANCELED: 'userCanceled', EDITOR_DESTROYED: 'editorDestroyed' }; /** * This experience tracks when the quick insert is opened. * * Start: When user types `/` to open quick insert or clicks the quick insert button * Success: When the quick insert menu is added to the DOM within 500ms of start * Failure: When 500ms passes without the quick insert menu being added to the DOM * Abort: When user presses escape or backspace */ export var getQuickInsertOpenExperiencePlugin = function getQuickInsertOpenExperiencePlugin(_ref) { var refs = _ref.refs, dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent; var targetEl; var editorViewEl; var mouseDownPos; var getTarget = function getTarget() { if (!targetEl) { targetEl = refs.popupsMountPoint || refs.wrapperElement || getPopupContainerFromEditorView(editorViewEl); } return targetEl; }; var experience = new Experience(EXPERIENCE_ID.MENU_OPEN, { actionSubjectId: ACTION_SUBJECT_ID.QUICK_INSERT, dispatchAnalyticsEvent: dispatchAnalyticsEvent, checks: [new ExperienceCheckTimeout({ durationMs: TIMEOUT_DURATION }), new ExperienceCheckDomMutation({ onDomMutation: function onDomMutation(_ref2) { var mutations = _ref2.mutations; if (mutations.some(isQuickInsertMenuAddedInMutation)) { return { status: 'success' }; } }, observeConfig: function observeConfig() { return { target: getTarget(), options: { childList: true } }; } })] }); return new SafePlugin({ key: pluginKey, props: { handleDOMEvents: { mousedown: function mousedown(_view, event) { if (isTargetQuickInsertButton(event.target)) { mouseDownPos = { x: event.clientX, y: event.clientY }; } }, mouseup: function mouseup(_view, event) { if (mouseDownPos && isTargetQuickInsertButton(event.target) && event.clientX === mouseDownPos.x && event.clientY === mouseDownPos.y) { experience.start({ method: START_METHOD.QUICK_INSERT_BUTTON }); } mouseDownPos = undefined; }, beforeinput: function beforeinput(view, event) { if (isQuickInsertTrigger(event) && isSelectionWhichSupportsTypeahead(view) && !isQuickInsertMenuWithinNode(getTarget())) { experience.start({ method: START_METHOD.TYPEAHEAD, forceRestart: true }); } }, keydown: function keydown(_view, event) { if (isCancelKey(event.key) && !isQuickInsertMenuWithinNode(getTarget())) { experience.abort({ reason: ABORT_REASON.USER_CANCELED }); } } } }, view: function view(editorView) { editorViewEl = editorView.dom; return { destroy: function destroy() { experience.abort({ reason: ABORT_REASON.EDITOR_DESTROYED }); } }; } }); }; var isQuickInsertTrigger = function isQuickInsertTrigger(_ref3) { var inputType = _ref3.inputType, data = _ref3.data; return inputType === 'insertText' && data === '/'; }; var isSelectionWhichSupportsTypeahead = function isSelectionWhichSupportsTypeahead(_ref4) { var _nodeBefore$textConte; var state = _ref4.state; var _state$selection = state.selection, from = _state$selection.from, $from = _state$selection.$from; if ($from.parent.type.name === 'codeBlock') { return false; } if ($from.marks().some(function (mark) { return mark.type.name === 'code'; })) { return false; } if (from === 0) { return true; } var nodeBefore = state.doc.resolve(from).nodeBefore; if (!nodeBefore) { return true; } var charBefore = ((_nodeBefore$textConte = nodeBefore.textContent) === null || _nodeBefore$textConte === void 0 ? void 0 : _nodeBefore$textConte.slice(-1)) || ''; return charBefore.trim().length === 0; }; var isCancelKey = function isCancelKey(key) { return key === 'Escape' || key === 'Backspace'; }; var isTargetQuickInsertButton = function isTargetQuickInsertButton(target) { return target instanceof HTMLElement && (target.dataset.testid === 'editor-quick-insert-button' || !!target.closest('[data-testid="editor-quick-insert-button"]')); }; var isQuickInsertMenuAddedInMutation = function isQuickInsertMenuAddedInMutation(_ref5) { var type = _ref5.type, addedNodes = _ref5.addedNodes; return type === 'childList' && _toConsumableArray(addedNodes).some(isQuickInsertMenuWithinNode); }; var isQuickInsertMenuWithinNode = function isQuickInsertMenuWithinNode(node) { return containsPopupWithNestedElement(node, '.fabric-editor-typeahead'); };