@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
84 lines (80 loc) • 3.77 kB
JavaScript
import { deleteSelectedRange } from '@atlaskit/editor-common/selection';
import { stopPreservingSelection } from '../pm-plugins/selection-preservation/editor-commands';
var getKeyboardEventInfo = function getKeyboardEventInfo(event) {
var key = event.key.toLowerCase();
var isMetaCtrl = event.metaKey || event.ctrlKey;
var isDelete = ['backspace', 'delete'].includes(key);
var isCut = isMetaCtrl && key === 'x';
var isPaste = isMetaCtrl && key === 'v';
var isUndo = isMetaCtrl && key === 'z' && !event.shiftKey;
var isRedo = isMetaCtrl && (key === 'y' || key === 'z' && event.shiftKey);
var isDestructive = isDelete || isCut || isPaste || isUndo || isRedo;
var isModifierOnly = ['control', 'meta', 'alt', 'shift'].includes(key) && !isMetaCtrl;
var isCopy = isMetaCtrl && key === 'c';
var isInert = isModifierOnly || isCopy;
return {
isDelete: isDelete,
isDestructive: isDestructive,
isInert: isInert
};
};
/**
* Handles key presses when a selection is being preserved, when the block menu is open or closed.
*
* Based on the key pressed and whether the block menu is open or closed:
* 1. Handles key presses with custom logic (e.g. delete/backspace)
* 2. Closes the block menu
* 3. Stops preserving the selection
*
* This is used in two places:
* 1. selection preservation plugin when selection is being preserved, and focus is in the editor.
* 2. block menu UI component when focus is in the block menu.
*
* Ensures consistent behaviour for key presses in both scenarios.
*/
export var handleKeyDownWithPreservedSelection = function handleKeyDownWithPreservedSelection(api) {
return function (event) {
return function (_ref) {
var _api$userIntent;
var tr = _ref.tr;
if (!api) {
return tr;
}
var _getKeyboardEventInfo = getKeyboardEventInfo(event),
isDelete = _getKeyboardEventInfo.isDelete,
isDestructive = _getKeyboardEventInfo.isDestructive,
isInert = _getKeyboardEventInfo.isInert;
// Handle delete/backspace key presses with custom logic to ensure preserved selection is used
if (isDelete) {
var _api$blockControls;
tr = deleteSelectedRange(tr, (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection);
}
var isBlockMenuOpen = ((_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent) === 'blockMenuOpen';
// When selected content is being removed/modified/undo/redo and the block menu is open
// close the block menu and refocus the editor
var shouldCloseBlockMenu = isDestructive && isBlockMenuOpen;
if (shouldCloseBlockMenu) {
var _api$blockControls2;
(_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
closeMenu: true
})({
tr: tr
});
api.core.actions.focus({
scrollIntoView: false
});
}
// Stop preserving when:
// 1. Content is being removed (delete/cut/paste) OR
// 2. Menu is closed AND user pressed a non-inert key (i.e. action which modifies selection or content)
// 3. undo/redo actions
var shouldStopPreservingSelection = isDestructive || !isBlockMenuOpen && !isInert;
if (shouldStopPreservingSelection) {
stopPreservingSelection({
tr: tr
});
}
return tr;
};
};
};