@atlaskit/editor-plugin-block-menu 6.0.22 → 6.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/blockMenuPlugin.js +6 -0
- package/dist/cjs/pm-plugins/keymap.js +61 -0
- package/dist/cjs/pm-plugins/main.js +3 -8
- package/dist/cjs/pm-plugins/utils/shouldSuppressKeyboardEvent.js +37 -0
- package/dist/cjs/ui/copy-link.js +7 -1
- package/dist/es2019/blockMenuPlugin.js +4 -0
- package/dist/es2019/pm-plugins/keymap.js +56 -0
- package/dist/es2019/pm-plugins/main.js +3 -8
- package/dist/es2019/pm-plugins/utils/shouldSuppressKeyboardEvent.js +31 -0
- package/dist/es2019/ui/copy-link.js +8 -2
- package/dist/esm/blockMenuPlugin.js +6 -0
- package/dist/esm/pm-plugins/keymap.js +55 -0
- package/dist/esm/pm-plugins/main.js +3 -8
- package/dist/esm/pm-plugins/utils/shouldSuppressKeyboardEvent.js +31 -0
- package/dist/esm/ui/copy-link.js +8 -2
- package/dist/types/pm-plugins/keymap.d.ts +4 -0
- package/dist/types/pm-plugins/utils/shouldSuppressKeyboardEvent.d.ts +14 -0
- package/dist/types-ts4.5/pm-plugins/keymap.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/utils/shouldSuppressKeyboardEvent.d.ts +14 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 6.0.24
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 6.0.23
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`0d8216e610e34`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0d8216e610e34) -
|
|
14
|
+
[ux] Add cmd-option-a shortcut for copylink to block from block menu
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
3
17
|
## 6.0.22
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -10,6 +10,7 @@ var _editorActions = require("./editor-actions");
|
|
|
10
10
|
var _isTransformToTargetDisabled = require("./editor-actions/isTransformToTargetDisabled");
|
|
11
11
|
var _formatNode2 = require("./editor-commands/formatNode");
|
|
12
12
|
var _transformNode2 = require("./editor-commands/transformNode");
|
|
13
|
+
var _keymap = require("./pm-plugins/keymap");
|
|
13
14
|
var _main = require("./pm-plugins/main");
|
|
14
15
|
var _blockMenu = _interopRequireDefault(require("./ui/block-menu"));
|
|
15
16
|
var _blockMenuComponents = require("./ui/block-menu-components");
|
|
@@ -31,6 +32,11 @@ var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
|
|
|
31
32
|
plugin: function plugin() {
|
|
32
33
|
return (0, _main.createPlugin)(api);
|
|
33
34
|
}
|
|
35
|
+
}, {
|
|
36
|
+
name: 'blockMenuKeymap',
|
|
37
|
+
plugin: function plugin() {
|
|
38
|
+
return (0, _keymap.keymapPlugin)(api, config);
|
|
39
|
+
}
|
|
34
40
|
}];
|
|
35
41
|
},
|
|
36
42
|
actions: {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.keymapPlugin = keymapPlugin;
|
|
7
|
+
var _keymaps = require("@atlaskit/editor-common/keymaps");
|
|
8
|
+
var _selection = require("@atlaskit/editor-common/selection");
|
|
9
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
10
|
+
var _blockMenuPluginType = require("../blockMenuPluginType");
|
|
11
|
+
var _main = require("../pm-plugins/main");
|
|
12
|
+
var _copyLink = require("../ui/utils/copyLink");
|
|
13
|
+
function keymapPlugin(api, config) {
|
|
14
|
+
var list = {};
|
|
15
|
+
var copyLinkToBlockCommand = function copyLinkToBlockCommand(state, dispatch) {
|
|
16
|
+
var _api$blockControls, _node$attrs;
|
|
17
|
+
// Check if feature flag is enabled
|
|
18
|
+
if (!(0, _platformFeatureFlags.fg)('platform_editor_adf_with_localid')) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Get the preserved selection (only works when block menu is open and selection is preserved)
|
|
23
|
+
var selection = api === null || api === void 0 || (_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;
|
|
24
|
+
if (!selection) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Check if the selection has a valid block range with localId
|
|
29
|
+
var blockRange = (0, _selection.expandSelectionToBlockRange)(selection);
|
|
30
|
+
if (!blockRange) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
var node = blockRange.$from.nodeAfter;
|
|
34
|
+
if (!(node !== null && node !== void 0 && (_node$attrs = node.attrs) !== null && _node$attrs !== void 0 && _node$attrs.localId)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Execute the copy link action
|
|
39
|
+
var _ref = config || {},
|
|
40
|
+
getLinkPath = _ref.getLinkPath,
|
|
41
|
+
blockLinkHashPrefix = _ref.blockLinkHashPrefix;
|
|
42
|
+
(0, _copyLink.copyLink)({
|
|
43
|
+
getLinkPath: getLinkPath,
|
|
44
|
+
blockLinkHashPrefix: blockLinkHashPrefix,
|
|
45
|
+
selection: selection
|
|
46
|
+
}).then(function (success) {
|
|
47
|
+
if (success && dispatch) {
|
|
48
|
+
dispatch(state.tr.setMeta(_main.blockMenuPluginKey, {
|
|
49
|
+
showFlag: _blockMenuPluginType.FLAG_ID.LINK_COPIED_TO_CLIPBOARD
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return true;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Ignored via go/ees005
|
|
57
|
+
(0, _keymaps.bindKeymapWithCommand)(
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
59
|
+
_keymaps.copyLinkToBlock.common, copyLinkToBlockCommand, list);
|
|
60
|
+
return (0, _keymaps.keymap)(list);
|
|
61
|
+
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.createPlugin = exports.blockMenuPluginKey = void 0;
|
|
7
7
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
8
8
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
9
|
+
var _shouldSuppressKeyboardEvent = require("./utils/shouldSuppressKeyboardEvent");
|
|
9
10
|
var blockMenuPluginKey = exports.blockMenuPluginKey = new _state.PluginKey('blockMenuPlugin');
|
|
10
11
|
var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
11
12
|
return new _safePlugin.SafePlugin({
|
|
@@ -35,14 +36,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// Block further handling of key events when block menu is open
|
|
38
|
-
// Except for backspace/delete/copy/cut/paste/undo/redo which should be handled by the selection preservation plugin
|
|
39
|
-
|
|
40
|
-
var isMetaCtrl = event.metaKey || event.ctrlKey;
|
|
41
|
-
var isBackspaceDelete = ['backspace', 'delete'].includes(key);
|
|
42
|
-
var isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
|
|
43
|
-
var isUndoRedo = isMetaCtrl && ['z', 'y'].includes(key);
|
|
44
|
-
var suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete && !isUndoRedo;
|
|
45
|
-
return suppressNativeHandling;
|
|
39
|
+
// Except for backspace/delete/copy/cut/paste/undo/redo/copy-link-to-block which should be handled by the selection preservation plugin
|
|
40
|
+
return (0, _shouldSuppressKeyboardEvent.shouldSuppressKeyboardEvent)(event);
|
|
46
41
|
}
|
|
47
42
|
}
|
|
48
43
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.shouldSuppressKeyboardEvent = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Determines whether keyboard events should be suppressed when the block menu is open.
|
|
9
|
+
*
|
|
10
|
+
* When the block menu is open, we want to block most keyboard events to prevent
|
|
11
|
+
* unintended interactions. However, certain actions should still be allowed:
|
|
12
|
+
* - Backspace/Delete: Allow deleting selected content
|
|
13
|
+
* - Copy/Cut/Paste: Allow clipboard operations (Cmd/Ctrl+C, Cmd/Ctrl+X, Cmd/Ctrl+V)
|
|
14
|
+
* - Undo/Redo: Allow undo/redo operations (Cmd/Ctrl+Z, Cmd/Ctrl+Y)
|
|
15
|
+
* - Copy Link to Block: Allow the keyboard shortcut (Cmd/Ctrl+Alt+A)
|
|
16
|
+
*
|
|
17
|
+
* @param event - The keyboard event to check
|
|
18
|
+
* @returns true if the event should be suppressed, false if it should be allowed
|
|
19
|
+
*/
|
|
20
|
+
var shouldSuppressKeyboardEvent = exports.shouldSuppressKeyboardEvent = function shouldSuppressKeyboardEvent(event) {
|
|
21
|
+
var key = event.key.toLowerCase();
|
|
22
|
+
var code = event.code.toLowerCase();
|
|
23
|
+
var isMetaCtrl = event.metaKey || event.ctrlKey;
|
|
24
|
+
var isAlt = event.altKey;
|
|
25
|
+
|
|
26
|
+
// Check for allowed keyboard shortcuts
|
|
27
|
+
var isBackspaceDelete = ['backspace', 'delete'].includes(key);
|
|
28
|
+
var isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
|
|
29
|
+
var isUndoRedo = isMetaCtrl && ['z', 'y'].includes(key);
|
|
30
|
+
|
|
31
|
+
// Use event.code to detect physical key 'A' because on macOS Option+A produces 'å'
|
|
32
|
+
var isCopyLinkToBlock = isMetaCtrl && isAlt && code === 'keya';
|
|
33
|
+
|
|
34
|
+
// Suppress all events except the allowed ones
|
|
35
|
+
var suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete && !isUndoRedo && !isCopyLinkToBlock;
|
|
36
|
+
return suppressNativeHandling;
|
|
37
|
+
};
|
package/dist/cjs/ui/copy-link.js
CHANGED
|
@@ -10,6 +10,7 @@ var _react = _interopRequireWildcard(require("react"));
|
|
|
10
10
|
var _reactIntlNext = require("react-intl-next");
|
|
11
11
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
12
12
|
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
13
|
+
var _keymaps = require("@atlaskit/editor-common/keymaps");
|
|
13
14
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
14
15
|
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
15
16
|
var _link = _interopRequireDefault(require("@atlaskit/icon/core/link"));
|
|
@@ -30,6 +31,7 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
|
|
|
30
31
|
var _ref2 = config || {},
|
|
31
32
|
getLinkPath = _ref2.getLinkPath,
|
|
32
33
|
blockLinkHashPrefix = _ref2.blockLinkHashPrefix;
|
|
34
|
+
var shortcut = (0, _keymaps.formatShortcut)(_keymaps.copyLinkToBlock);
|
|
33
35
|
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls', 'selection'], function (_ref3) {
|
|
34
36
|
var blockControlsState = _ref3.blockControlsState,
|
|
35
37
|
selectionState = _ref3.selectionState;
|
|
@@ -90,7 +92,11 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
|
|
|
90
92
|
onClick: handleClick,
|
|
91
93
|
elemBefore: /*#__PURE__*/_react.default.createElement(_link.default, {
|
|
92
94
|
label: ""
|
|
93
|
-
})
|
|
95
|
+
}),
|
|
96
|
+
elemAfter: shortcut ? /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarKeyboardShortcutHint, {
|
|
97
|
+
shortcut: shortcut
|
|
98
|
+
}) : undefined,
|
|
99
|
+
ariaKeyshortcuts: shortcut
|
|
94
100
|
}, formatMessage(_messages.blockMenuMessages.copyLinkToBlock));
|
|
95
101
|
};
|
|
96
102
|
var CopyLinkDropdownItem = exports.CopyLinkDropdownItem = (0, _reactIntlNext.injectIntl)(CopyLinkDropdownItemContent);
|
|
@@ -3,6 +3,7 @@ import { createBlockMenuRegistry } from './editor-actions';
|
|
|
3
3
|
import { isTransformToTargetDisabled } from './editor-actions/isTransformToTargetDisabled';
|
|
4
4
|
import { formatNode } from './editor-commands/formatNode';
|
|
5
5
|
import { transformNode } from './editor-commands/transformNode';
|
|
6
|
+
import { keymapPlugin } from './pm-plugins/keymap';
|
|
6
7
|
import { blockMenuPluginKey, createPlugin } from './pm-plugins/main';
|
|
7
8
|
import BlockMenu from './ui/block-menu';
|
|
8
9
|
import { getBlockMenuComponents } from './ui/block-menu-components';
|
|
@@ -23,6 +24,9 @@ export const blockMenuPlugin = ({
|
|
|
23
24
|
return [{
|
|
24
25
|
name: 'blockMenuPlugin',
|
|
25
26
|
plugin: () => createPlugin(api)
|
|
27
|
+
}, {
|
|
28
|
+
name: 'blockMenuKeymap',
|
|
29
|
+
plugin: () => keymapPlugin(api, config)
|
|
26
30
|
}];
|
|
27
31
|
},
|
|
28
32
|
actions: {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { bindKeymapWithCommand, copyLinkToBlock, keymap } from '@atlaskit/editor-common/keymaps';
|
|
2
|
+
import { expandSelectionToBlockRange } from '@atlaskit/editor-common/selection';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import { FLAG_ID } from '../blockMenuPluginType';
|
|
5
|
+
import { blockMenuPluginKey } from '../pm-plugins/main';
|
|
6
|
+
import { copyLink } from '../ui/utils/copyLink';
|
|
7
|
+
export function keymapPlugin(api, config) {
|
|
8
|
+
const list = {};
|
|
9
|
+
const copyLinkToBlockCommand = (state, dispatch) => {
|
|
10
|
+
var _api$blockControls, _api$blockControls$sh, _node$attrs;
|
|
11
|
+
// Check if feature flag is enabled
|
|
12
|
+
if (!fg('platform_editor_adf_with_localid')) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Get the preserved selection (only works when block menu is open and selection is preserved)
|
|
17
|
+
const selection = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$sh = _api$blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
|
|
18
|
+
if (!selection) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check if the selection has a valid block range with localId
|
|
23
|
+
const blockRange = expandSelectionToBlockRange(selection);
|
|
24
|
+
if (!blockRange) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const node = blockRange.$from.nodeAfter;
|
|
28
|
+
if (!(node !== null && node !== void 0 && (_node$attrs = node.attrs) !== null && _node$attrs !== void 0 && _node$attrs.localId)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Execute the copy link action
|
|
33
|
+
const {
|
|
34
|
+
getLinkPath,
|
|
35
|
+
blockLinkHashPrefix
|
|
36
|
+
} = config || {};
|
|
37
|
+
copyLink({
|
|
38
|
+
getLinkPath,
|
|
39
|
+
blockLinkHashPrefix,
|
|
40
|
+
selection
|
|
41
|
+
}).then(success => {
|
|
42
|
+
if (success && dispatch) {
|
|
43
|
+
dispatch(state.tr.setMeta(blockMenuPluginKey, {
|
|
44
|
+
showFlag: FLAG_ID.LINK_COPIED_TO_CLIPBOARD
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return true;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Ignored via go/ees005
|
|
52
|
+
bindKeymapWithCommand(
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
54
|
+
copyLinkToBlock.common, copyLinkToBlockCommand, list);
|
|
55
|
+
return keymap(list);
|
|
56
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
2
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import { shouldSuppressKeyboardEvent } from './utils/shouldSuppressKeyboardEvent';
|
|
3
4
|
export const blockMenuPluginKey = new PluginKey('blockMenuPlugin');
|
|
4
5
|
export const createPlugin = api => {
|
|
5
6
|
return new SafePlugin({
|
|
@@ -29,14 +30,8 @@ export const createPlugin = api => {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
// Block further handling of key events when block menu is open
|
|
32
|
-
// Except for backspace/delete/copy/cut/paste/undo/redo which should be handled by the selection preservation plugin
|
|
33
|
-
|
|
34
|
-
const isMetaCtrl = event.metaKey || event.ctrlKey;
|
|
35
|
-
const isBackspaceDelete = ['backspace', 'delete'].includes(key);
|
|
36
|
-
const isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
|
|
37
|
-
const isUndoRedo = isMetaCtrl && ['z', 'y'].includes(key);
|
|
38
|
-
const suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete && !isUndoRedo;
|
|
39
|
-
return suppressNativeHandling;
|
|
33
|
+
// Except for backspace/delete/copy/cut/paste/undo/redo/copy-link-to-block which should be handled by the selection preservation plugin
|
|
34
|
+
return shouldSuppressKeyboardEvent(event);
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
37
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether keyboard events should be suppressed when the block menu is open.
|
|
3
|
+
*
|
|
4
|
+
* When the block menu is open, we want to block most keyboard events to prevent
|
|
5
|
+
* unintended interactions. However, certain actions should still be allowed:
|
|
6
|
+
* - Backspace/Delete: Allow deleting selected content
|
|
7
|
+
* - Copy/Cut/Paste: Allow clipboard operations (Cmd/Ctrl+C, Cmd/Ctrl+X, Cmd/Ctrl+V)
|
|
8
|
+
* - Undo/Redo: Allow undo/redo operations (Cmd/Ctrl+Z, Cmd/Ctrl+Y)
|
|
9
|
+
* - Copy Link to Block: Allow the keyboard shortcut (Cmd/Ctrl+Alt+A)
|
|
10
|
+
*
|
|
11
|
+
* @param event - The keyboard event to check
|
|
12
|
+
* @returns true if the event should be suppressed, false if it should be allowed
|
|
13
|
+
*/
|
|
14
|
+
export const shouldSuppressKeyboardEvent = event => {
|
|
15
|
+
const key = event.key.toLowerCase();
|
|
16
|
+
const code = event.code.toLowerCase();
|
|
17
|
+
const isMetaCtrl = event.metaKey || event.ctrlKey;
|
|
18
|
+
const isAlt = event.altKey;
|
|
19
|
+
|
|
20
|
+
// Check for allowed keyboard shortcuts
|
|
21
|
+
const isBackspaceDelete = ['backspace', 'delete'].includes(key);
|
|
22
|
+
const isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
|
|
23
|
+
const isUndoRedo = isMetaCtrl && ['z', 'y'].includes(key);
|
|
24
|
+
|
|
25
|
+
// Use event.code to detect physical key 'A' because on macOS Option+A produces 'å'
|
|
26
|
+
const isCopyLinkToBlock = isMetaCtrl && isAlt && code === 'keya';
|
|
27
|
+
|
|
28
|
+
// Suppress all events except the allowed ones
|
|
29
|
+
const suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete && !isUndoRedo && !isCopyLinkToBlock;
|
|
30
|
+
return suppressNativeHandling;
|
|
31
|
+
};
|
|
@@ -2,8 +2,9 @@ import React, { useCallback } from 'react';
|
|
|
2
2
|
import { injectIntl, useIntl } from 'react-intl-next';
|
|
3
3
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
5
|
+
import { copyLinkToBlock, formatShortcut } from '@atlaskit/editor-common/keymaps';
|
|
5
6
|
import { blockMenuMessages as messages } from '@atlaskit/editor-common/messages';
|
|
6
|
-
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
7
|
+
import { ToolbarDropdownItem, ToolbarKeyboardShortcutHint } from '@atlaskit/editor-toolbar';
|
|
7
8
|
import LinkIcon from '@atlaskit/icon/core/link';
|
|
8
9
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
10
|
import { FLAG_ID } from '../blockMenuPluginType';
|
|
@@ -25,6 +26,7 @@ const CopyLinkDropdownItemContent = ({
|
|
|
25
26
|
getLinkPath,
|
|
26
27
|
blockLinkHashPrefix
|
|
27
28
|
} = config || {};
|
|
29
|
+
const shortcut = formatShortcut(copyLinkToBlock);
|
|
28
30
|
const {
|
|
29
31
|
preservedSelection,
|
|
30
32
|
defaultSelection
|
|
@@ -89,7 +91,11 @@ const CopyLinkDropdownItemContent = ({
|
|
|
89
91
|
onClick: handleClick,
|
|
90
92
|
elemBefore: /*#__PURE__*/React.createElement(LinkIcon, {
|
|
91
93
|
label: ""
|
|
92
|
-
})
|
|
94
|
+
}),
|
|
95
|
+
elemAfter: shortcut ? /*#__PURE__*/React.createElement(ToolbarKeyboardShortcutHint, {
|
|
96
|
+
shortcut: shortcut
|
|
97
|
+
}) : undefined,
|
|
98
|
+
ariaKeyshortcuts: shortcut
|
|
93
99
|
}, formatMessage(messages.copyLinkToBlock));
|
|
94
100
|
};
|
|
95
101
|
export const CopyLinkDropdownItem = injectIntl(CopyLinkDropdownItemContent);
|
|
@@ -3,6 +3,7 @@ import { createBlockMenuRegistry } from './editor-actions';
|
|
|
3
3
|
import { isTransformToTargetDisabled } from './editor-actions/isTransformToTargetDisabled';
|
|
4
4
|
import { formatNode as _formatNode } from './editor-commands/formatNode';
|
|
5
5
|
import { transformNode as _transformNode } from './editor-commands/transformNode';
|
|
6
|
+
import { keymapPlugin } from './pm-plugins/keymap';
|
|
6
7
|
import { blockMenuPluginKey, createPlugin } from './pm-plugins/main';
|
|
7
8
|
import BlockMenu from './ui/block-menu';
|
|
8
9
|
import { getBlockMenuComponents } from './ui/block-menu-components';
|
|
@@ -24,6 +25,11 @@ export var blockMenuPlugin = function blockMenuPlugin(_ref) {
|
|
|
24
25
|
plugin: function plugin() {
|
|
25
26
|
return createPlugin(api);
|
|
26
27
|
}
|
|
28
|
+
}, {
|
|
29
|
+
name: 'blockMenuKeymap',
|
|
30
|
+
plugin: function plugin() {
|
|
31
|
+
return keymapPlugin(api, config);
|
|
32
|
+
}
|
|
27
33
|
}];
|
|
28
34
|
},
|
|
29
35
|
actions: {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { bindKeymapWithCommand, copyLinkToBlock, keymap } from '@atlaskit/editor-common/keymaps';
|
|
2
|
+
import { expandSelectionToBlockRange } from '@atlaskit/editor-common/selection';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import { FLAG_ID } from '../blockMenuPluginType';
|
|
5
|
+
import { blockMenuPluginKey } from '../pm-plugins/main';
|
|
6
|
+
import { copyLink } from '../ui/utils/copyLink';
|
|
7
|
+
export function keymapPlugin(api, config) {
|
|
8
|
+
var list = {};
|
|
9
|
+
var copyLinkToBlockCommand = function copyLinkToBlockCommand(state, dispatch) {
|
|
10
|
+
var _api$blockControls, _node$attrs;
|
|
11
|
+
// Check if feature flag is enabled
|
|
12
|
+
if (!fg('platform_editor_adf_with_localid')) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Get the preserved selection (only works when block menu is open and selection is preserved)
|
|
17
|
+
var selection = api === null || api === void 0 || (_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;
|
|
18
|
+
if (!selection) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check if the selection has a valid block range with localId
|
|
23
|
+
var blockRange = expandSelectionToBlockRange(selection);
|
|
24
|
+
if (!blockRange) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
var node = blockRange.$from.nodeAfter;
|
|
28
|
+
if (!(node !== null && node !== void 0 && (_node$attrs = node.attrs) !== null && _node$attrs !== void 0 && _node$attrs.localId)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Execute the copy link action
|
|
33
|
+
var _ref = config || {},
|
|
34
|
+
getLinkPath = _ref.getLinkPath,
|
|
35
|
+
blockLinkHashPrefix = _ref.blockLinkHashPrefix;
|
|
36
|
+
copyLink({
|
|
37
|
+
getLinkPath: getLinkPath,
|
|
38
|
+
blockLinkHashPrefix: blockLinkHashPrefix,
|
|
39
|
+
selection: selection
|
|
40
|
+
}).then(function (success) {
|
|
41
|
+
if (success && dispatch) {
|
|
42
|
+
dispatch(state.tr.setMeta(blockMenuPluginKey, {
|
|
43
|
+
showFlag: FLAG_ID.LINK_COPIED_TO_CLIPBOARD
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Ignored via go/ees005
|
|
51
|
+
bindKeymapWithCommand(
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
53
|
+
copyLinkToBlock.common, copyLinkToBlockCommand, list);
|
|
54
|
+
return keymap(list);
|
|
55
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
2
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import { shouldSuppressKeyboardEvent } from './utils/shouldSuppressKeyboardEvent';
|
|
3
4
|
export var blockMenuPluginKey = new PluginKey('blockMenuPlugin');
|
|
4
5
|
export var createPlugin = function createPlugin(api) {
|
|
5
6
|
return new SafePlugin({
|
|
@@ -29,14 +30,8 @@ export var createPlugin = function createPlugin(api) {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
// Block further handling of key events when block menu is open
|
|
32
|
-
// Except for backspace/delete/copy/cut/paste/undo/redo which should be handled by the selection preservation plugin
|
|
33
|
-
|
|
34
|
-
var isMetaCtrl = event.metaKey || event.ctrlKey;
|
|
35
|
-
var isBackspaceDelete = ['backspace', 'delete'].includes(key);
|
|
36
|
-
var isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
|
|
37
|
-
var isUndoRedo = isMetaCtrl && ['z', 'y'].includes(key);
|
|
38
|
-
var suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete && !isUndoRedo;
|
|
39
|
-
return suppressNativeHandling;
|
|
33
|
+
// Except for backspace/delete/copy/cut/paste/undo/redo/copy-link-to-block which should be handled by the selection preservation plugin
|
|
34
|
+
return shouldSuppressKeyboardEvent(event);
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
37
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether keyboard events should be suppressed when the block menu is open.
|
|
3
|
+
*
|
|
4
|
+
* When the block menu is open, we want to block most keyboard events to prevent
|
|
5
|
+
* unintended interactions. However, certain actions should still be allowed:
|
|
6
|
+
* - Backspace/Delete: Allow deleting selected content
|
|
7
|
+
* - Copy/Cut/Paste: Allow clipboard operations (Cmd/Ctrl+C, Cmd/Ctrl+X, Cmd/Ctrl+V)
|
|
8
|
+
* - Undo/Redo: Allow undo/redo operations (Cmd/Ctrl+Z, Cmd/Ctrl+Y)
|
|
9
|
+
* - Copy Link to Block: Allow the keyboard shortcut (Cmd/Ctrl+Alt+A)
|
|
10
|
+
*
|
|
11
|
+
* @param event - The keyboard event to check
|
|
12
|
+
* @returns true if the event should be suppressed, false if it should be allowed
|
|
13
|
+
*/
|
|
14
|
+
export var shouldSuppressKeyboardEvent = function shouldSuppressKeyboardEvent(event) {
|
|
15
|
+
var key = event.key.toLowerCase();
|
|
16
|
+
var code = event.code.toLowerCase();
|
|
17
|
+
var isMetaCtrl = event.metaKey || event.ctrlKey;
|
|
18
|
+
var isAlt = event.altKey;
|
|
19
|
+
|
|
20
|
+
// Check for allowed keyboard shortcuts
|
|
21
|
+
var isBackspaceDelete = ['backspace', 'delete'].includes(key);
|
|
22
|
+
var isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
|
|
23
|
+
var isUndoRedo = isMetaCtrl && ['z', 'y'].includes(key);
|
|
24
|
+
|
|
25
|
+
// Use event.code to detect physical key 'A' because on macOS Option+A produces 'å'
|
|
26
|
+
var isCopyLinkToBlock = isMetaCtrl && isAlt && code === 'keya';
|
|
27
|
+
|
|
28
|
+
// Suppress all events except the allowed ones
|
|
29
|
+
var suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete && !isUndoRedo && !isCopyLinkToBlock;
|
|
30
|
+
return suppressNativeHandling;
|
|
31
|
+
};
|
package/dist/esm/ui/copy-link.js
CHANGED
|
@@ -2,8 +2,9 @@ import React, { useCallback } from 'react';
|
|
|
2
2
|
import { injectIntl, useIntl } from 'react-intl-next';
|
|
3
3
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
5
|
+
import { copyLinkToBlock, formatShortcut } from '@atlaskit/editor-common/keymaps';
|
|
5
6
|
import { blockMenuMessages as messages } from '@atlaskit/editor-common/messages';
|
|
6
|
-
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
7
|
+
import { ToolbarDropdownItem, ToolbarKeyboardShortcutHint } from '@atlaskit/editor-toolbar';
|
|
7
8
|
import LinkIcon from '@atlaskit/icon/core/link';
|
|
8
9
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
10
|
import { FLAG_ID } from '../blockMenuPluginType';
|
|
@@ -21,6 +22,7 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
|
|
|
21
22
|
var _ref2 = config || {},
|
|
22
23
|
getLinkPath = _ref2.getLinkPath,
|
|
23
24
|
blockLinkHashPrefix = _ref2.blockLinkHashPrefix;
|
|
25
|
+
var shortcut = formatShortcut(copyLinkToBlock);
|
|
24
26
|
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['blockControls', 'selection'], function (_ref3) {
|
|
25
27
|
var blockControlsState = _ref3.blockControlsState,
|
|
26
28
|
selectionState = _ref3.selectionState;
|
|
@@ -81,7 +83,11 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
|
|
|
81
83
|
onClick: handleClick,
|
|
82
84
|
elemBefore: /*#__PURE__*/React.createElement(LinkIcon, {
|
|
83
85
|
label: ""
|
|
84
|
-
})
|
|
86
|
+
}),
|
|
87
|
+
elemAfter: shortcut ? /*#__PURE__*/React.createElement(ToolbarKeyboardShortcutHint, {
|
|
88
|
+
shortcut: shortcut
|
|
89
|
+
}) : undefined,
|
|
90
|
+
ariaKeyshortcuts: shortcut
|
|
85
91
|
}, formatMessage(messages.copyLinkToBlock));
|
|
86
92
|
};
|
|
87
93
|
export var CopyLinkDropdownItem = injectIntl(CopyLinkDropdownItemContent);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { BlockMenuPlugin, BlockMenuPluginOptions } from '../blockMenuPluginType';
|
|
4
|
+
export declare function keymapPlugin(api: ExtractInjectionAPI<BlockMenuPlugin> | undefined, config: BlockMenuPluginOptions | undefined): SafePlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether keyboard events should be suppressed when the block menu is open.
|
|
3
|
+
*
|
|
4
|
+
* When the block menu is open, we want to block most keyboard events to prevent
|
|
5
|
+
* unintended interactions. However, certain actions should still be allowed:
|
|
6
|
+
* - Backspace/Delete: Allow deleting selected content
|
|
7
|
+
* - Copy/Cut/Paste: Allow clipboard operations (Cmd/Ctrl+C, Cmd/Ctrl+X, Cmd/Ctrl+V)
|
|
8
|
+
* - Undo/Redo: Allow undo/redo operations (Cmd/Ctrl+Z, Cmd/Ctrl+Y)
|
|
9
|
+
* - Copy Link to Block: Allow the keyboard shortcut (Cmd/Ctrl+Alt+A)
|
|
10
|
+
*
|
|
11
|
+
* @param event - The keyboard event to check
|
|
12
|
+
* @returns true if the event should be suppressed, false if it should be allowed
|
|
13
|
+
*/
|
|
14
|
+
export declare const shouldSuppressKeyboardEvent: (event: KeyboardEvent) => boolean;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { BlockMenuPlugin, BlockMenuPluginOptions } from '../blockMenuPluginType';
|
|
4
|
+
export declare function keymapPlugin(api: ExtractInjectionAPI<BlockMenuPlugin> | undefined, config: BlockMenuPluginOptions | undefined): SafePlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether keyboard events should be suppressed when the block menu is open.
|
|
3
|
+
*
|
|
4
|
+
* When the block menu is open, we want to block most keyboard events to prevent
|
|
5
|
+
* unintended interactions. However, certain actions should still be allowed:
|
|
6
|
+
* - Backspace/Delete: Allow deleting selected content
|
|
7
|
+
* - Copy/Cut/Paste: Allow clipboard operations (Cmd/Ctrl+C, Cmd/Ctrl+X, Cmd/Ctrl+V)
|
|
8
|
+
* - Undo/Redo: Allow undo/redo operations (Cmd/Ctrl+Z, Cmd/Ctrl+Y)
|
|
9
|
+
* - Copy Link to Block: Allow the keyboard shortcut (Cmd/Ctrl+Alt+A)
|
|
10
|
+
*
|
|
11
|
+
* @param event - The keyboard event to check
|
|
12
|
+
* @returns true if the event should be suppressed, false if it should be allowed
|
|
13
|
+
*/
|
|
14
|
+
export declare const shouldSuppressKeyboardEvent: (event: KeyboardEvent) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.24",
|
|
4
4
|
"description": "BlockMenu plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
42
42
|
"@atlaskit/editor-toolbar": "^0.19.0",
|
|
43
43
|
"@atlaskit/flag": "^17.8.0",
|
|
44
|
-
"@atlaskit/icon": "^
|
|
44
|
+
"@atlaskit/icon": "^30.0.0",
|
|
45
45
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
46
46
|
"@atlaskit/platform-feature-flags-react": "^0.4.0",
|
|
47
47
|
"@atlaskit/primitives": "^17.1.0",
|
|
48
48
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
49
|
-
"@atlaskit/tmp-editor-statsig": "^16.
|
|
49
|
+
"@atlaskit/tmp-editor-statsig": "^16.30.0",
|
|
50
50
|
"@atlaskit/tokens": "^10.1.0",
|
|
51
51
|
"@babel/runtime": "^7.0.0"
|
|
52
52
|
},
|