@atlaskit/editor-plugin-block-menu
Version:
BlockMenu plugin for @atlaskit/editor-core
255 lines (252 loc) • 9.93 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getBlockMenuExperiencesPlugin = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _bindEventListener = require("bind-event-listener");
var _analytics = require("@atlaskit/editor-common/analytics");
var _blockMenu = require("@atlaskit/editor-common/block-menu");
var _experiences = require("@atlaskit/editor-common/experiences");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _state = require("@atlaskit/editor-prosemirror/state");
var _experienceCheckUtils = require("./experience-check-utils");
var TIMEOUT_DURATION = 1000;
var PORTAL_TEST_ID = {
LINK_COPIED_TO_CLIPBOARD: 'link-copied-to-clipboard',
SYNC_BLOCK_DELETE_CONFIRMATION: 'sync-block-delete-confirmation'
};
var pluginKey = new _state.PluginKey('blockMenuExperiences');
var START_METHOD = {
DRAG_HANDLE_CLICK: 'dragHandleClick',
KEYBOARD: 'keyboard'
};
var ABORT_REASON = {
USER_CANCELED: 'userCanceled',
EDITOR_DESTROYED: 'editorDestroyed'
};
var getBlockMenuExperiencesPlugin = exports.getBlockMenuExperiencesPlugin = function getBlockMenuExperiencesPlugin(_ref) {
var refs = _ref.refs,
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
var popupTargetEl;
var editorView;
var getPopupsTarget = function getPopupsTarget() {
if (!popupTargetEl) {
var _editorView;
popupTargetEl = refs.popupsMountPoint || (0, _experiences.getPopupContainerFromEditorView)((_editorView = editorView) === null || _editorView === void 0 ? void 0 : _editorView.dom);
}
return popupTargetEl;
};
var getEditorDom = function getEditorDom() {
var _editorView2;
if (((_editorView2 = editorView) === null || _editorView2 === void 0 ? void 0 : _editorView2.dom) instanceof HTMLElement) {
return editorView.dom;
}
return null;
};
var blockMenuOpenExperience = new _experiences.Experience(_experiences.EXPERIENCE_ID.MENU_OPEN, {
actionSubjectId: _analytics.ACTION_SUBJECT_ID.BLOCK_MENU,
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
checks: [new _experiences.ExperienceCheckTimeout({
durationMs: TIMEOUT_DURATION
}), new _experiences.ExperienceCheckPopupMutation({
nestedElementQuery: "[data-testid=\"".concat(_blockMenu.BLOCK_MENU_TEST_ID, "\"]"),
getTarget: getPopupsTarget,
type: 'editorContent'
})]
});
var observeConfigs = function observeConfigs() {
var narrowTarget = (0, _experiences.getSelectionAncestorDOM)(editorView);
var editorDom = getEditorDom();
return [].concat((0, _toConsumableArray2.default)(narrowTarget ? [{
target: narrowTarget,
options: {
childList: true,
subtree: true
}
}] : []), (0, _toConsumableArray2.default)(editorDom ? [{
target: editorDom,
options: {
childList: true
}
}] : []));
};
var blockMoveUpExperience = new _experiences.Experience(_experiences.EXPERIENCE_ID.MENU_ACTION, {
action: _analytics.ACTION.MOVED,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.MOVE_UP_BLOCK,
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
checks: [new _experiences.ExperienceCheckTimeout({
durationMs: TIMEOUT_DURATION
}), new _experiences.ExperienceCheckDomMutation({
onDomMutation: _experienceCheckUtils.handleMoveDomMutation,
observeConfig: observeConfigs
})]
});
var blockMoveDownExperience = new _experiences.Experience(_experiences.EXPERIENCE_ID.MENU_ACTION, {
action: _analytics.ACTION.MOVED,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.MOVE_DOWN_BLOCK,
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
checks: [new _experiences.ExperienceCheckTimeout({
durationMs: TIMEOUT_DURATION
}), new _experiences.ExperienceCheckDomMutation({
onDomMutation: _experienceCheckUtils.handleMoveDomMutation,
observeConfig: observeConfigs
})]
});
var blockDeleteExperience = new _experiences.Experience(_experiences.EXPERIENCE_ID.MENU_ACTION, {
action: _analytics.ACTION.DELETED,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.DELETE_BLOCK,
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
checks: [new _experiences.ExperienceCheckTimeout({
durationMs: TIMEOUT_DURATION
}), new _experiences.ExperienceCheckDomMutation({
onDomMutation: _experienceCheckUtils.handleDeleteDomMutation,
observeConfig: observeConfigs
}), new _experiences.ExperienceCheckPopupMutation({
nestedElementQuery: "[data-testid=\"".concat(PORTAL_TEST_ID.SYNC_BLOCK_DELETE_CONFIRMATION, "\"]"),
type: 'portalRoot'
})]
});
var blockTransformExperience = new _experiences.Experience(_experiences.EXPERIENCE_ID.MENU_ACTION, {
action: _analytics.ACTION.TRANSFORMED,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.TRANSFORM_BLOCK,
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
checks: [new _experiences.ExperienceCheckTimeout({
durationMs: TIMEOUT_DURATION
}), new _experiences.ExperienceCheckDomMutation({
onDomMutation: _experienceCheckUtils.handleTransformDomMutation,
observeConfig: observeConfigs
})]
});
var blockCopyLinkExperience = new _experiences.Experience(_experiences.EXPERIENCE_ID.MENU_ACTION, {
action: _analytics.ACTION.COPIED,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.COPY_LINK_TO_BLOCK,
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
checks: [new _experiences.ExperienceCheckTimeout({
durationMs: TIMEOUT_DURATION
}), new _experiences.ExperienceCheckPopupMutation({
nestedElementQuery: "[data-testid=\"".concat(PORTAL_TEST_ID.LINK_COPIED_TO_CLIPBOARD, "\"]"),
type: 'portalRoot'
})]
});
var handleMenuOpened = function handleMenuOpened(method) {
// Don't start if block menu is already visible
if ((0, _experienceCheckUtils.isBlockMenuVisible)(getPopupsTarget())) {
return;
}
blockMenuOpenExperience.start({
method: method
});
};
var handleTransformActioned = function handleTransformActioned(target) {
if (!target.closest('[data-testid="editor-turn-into-menu--content"]') ||
// Skip experience tracking when the clicked item is an extension menu item
// (e.g. Jira macro, etc.) - they don't perform block transforms
target.closest("[data-testid=\"".concat(_blockMenu.EXTENSION_MENU_ITEM_TEST_ID, "\"]"))) {
return false;
}
var turnIntoButton = target.closest('button');
if (turnIntoButton && turnIntoButton instanceof HTMLElement && !turnIntoButton.hasAttribute('disabled') && turnIntoButton.getAttribute('aria-disabled') !== 'true') {
blockTransformExperience.start();
}
return true;
};
var handleItemActioned = function handleItemActioned(target) {
if (handleTransformActioned(target)) {
return;
}
var button = target.closest('button[data-testid]');
if (!button || !(button instanceof HTMLButtonElement) || button.disabled || button.getAttribute('aria-disabled') === 'true') {
return;
}
var testId = button.dataset.testid;
if (!testId) {
return;
}
switch (testId) {
case _blockMenu.BLOCK_MENU_ACTION_TEST_ID.MOVE_UP:
blockMoveUpExperience.start();
break;
case _blockMenu.BLOCK_MENU_ACTION_TEST_ID.MOVE_DOWN:
blockMoveDownExperience.start();
break;
case _blockMenu.BLOCK_MENU_ACTION_TEST_ID.DELETE:
blockDeleteExperience.start();
break;
case _blockMenu.BLOCK_MENU_ACTION_TEST_ID.COPY_LINK:
blockCopyLinkExperience.start();
break;
}
};
var unbindClickListener = (0, _bindEventListener.bind)(document, {
type: 'click',
listener: function listener(event) {
var target = event.target;
if (!(target instanceof HTMLElement)) {
return;
}
if ((0, _experienceCheckUtils.isDragHandleElement)(target)) {
handleMenuOpened(START_METHOD.DRAG_HANDLE_CLICK);
} else {
handleItemActioned(target);
}
},
options: {
capture: true
}
});
var unbindKeydownListener = (0, _bindEventListener.bind)(document, {
type: 'keydown',
listener: function listener(event) {
var target = event.target;
if (!(target instanceof HTMLElement)) {
return;
}
// Check if Enter or Space is pressed on a drag handle
if ((event.key === 'Enter' || event.key === ' ') && (0, _experienceCheckUtils.isDragHandleElement)(target)) {
handleMenuOpened(START_METHOD.KEYBOARD);
}
// Abort on Escape key if block menu is not yet visible
if (event.key === 'Escape' && !(0, _experienceCheckUtils.isBlockMenuVisible)(getPopupsTarget())) {
blockMenuOpenExperience.abort({
reason: ABORT_REASON.USER_CANCELED
});
}
},
options: {
capture: true
}
});
return new _safePlugin.SafePlugin({
key: pluginKey,
view: function view(_view) {
editorView = _view;
return {
destroy: function destroy() {
blockMenuOpenExperience.abort({
reason: ABORT_REASON.EDITOR_DESTROYED
});
blockMoveUpExperience.abort({
reason: ABORT_REASON.EDITOR_DESTROYED
});
blockMoveDownExperience.abort({
reason: ABORT_REASON.EDITOR_DESTROYED
});
blockDeleteExperience.abort({
reason: ABORT_REASON.EDITOR_DESTROYED
});
blockTransformExperience.abort({
reason: ABORT_REASON.EDITOR_DESTROYED
});
blockCopyLinkExperience.abort({
reason: ABORT_REASON.EDITOR_DESTROYED
});
editorView = undefined;
unbindClickListener();
unbindKeydownListener();
}
};
}
});
};