@atlaskit/editor-plugin-block-menu 0.0.6 → 0.0.8
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 +16 -0
- package/dist/cjs/ui/block-menu-components.js +26 -2
- package/dist/cjs/ui/block-menu.js +7 -2
- package/dist/cjs/ui/copy-block.js +82 -0
- package/dist/es2019/ui/block-menu-components.js +27 -2
- package/dist/es2019/ui/block-menu.js +7 -2
- package/dist/es2019/ui/copy-block.js +75 -0
- package/dist/esm/ui/block-menu-components.js +26 -2
- package/dist/esm/ui/block-menu.js +7 -2
- package/dist/esm/ui/copy-block.js +75 -0
- package/dist/types/blockMenuPluginType.d.ts +6 -1
- package/dist/types/ui/copy-block.d.ts +11 -0
- package/dist/types-ts4.5/blockMenuPluginType.d.ts +3 -1
- package/dist/types-ts4.5/ui/copy-block.d.ts +11 -0
- package/package.json +2 -2
- package/tsconfig.json +1 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 0.0.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`1bed58ba517b7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1bed58ba517b7) -
|
|
8
|
+
[ux] BlockMenu will be opened to the left or the drag handle by default and to the right when
|
|
9
|
+
there is no enough space.
|
|
10
|
+
|
|
11
|
+
## 0.0.7
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`31fc6b9e10762`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/31fc6b9e10762) -
|
|
16
|
+
[ux] ED-28592 ED-28592:Add copy block menu item to block menu
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
|
|
3
19
|
## 0.0.6
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -14,6 +14,7 @@ var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-
|
|
|
14
14
|
var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete"));
|
|
15
15
|
var _listBulleted = _interopRequireDefault(require("@atlaskit/icon/core/list-bulleted"));
|
|
16
16
|
var _task = _interopRequireDefault(require("@atlaskit/icon/core/task"));
|
|
17
|
+
var _copyBlock = _interopRequireDefault(require("./copy-block"));
|
|
17
18
|
var _moveDown = require("./move-down");
|
|
18
19
|
var _moveUp = require("./move-up");
|
|
19
20
|
var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(api) {
|
|
@@ -60,7 +61,7 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
|
|
|
60
61
|
}
|
|
61
62
|
}, {
|
|
62
63
|
type: 'block-menu-section',
|
|
63
|
-
key: 'block-menu-section-
|
|
64
|
+
key: 'block-menu-section-copy',
|
|
64
65
|
rank: 200,
|
|
65
66
|
component: function component(_ref2) {
|
|
66
67
|
var children = _ref2.children;
|
|
@@ -68,9 +69,22 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
|
|
|
68
69
|
hasSeparator: true
|
|
69
70
|
}, children);
|
|
70
71
|
}
|
|
72
|
+
}, {
|
|
73
|
+
type: 'block-menu-item',
|
|
74
|
+
key: 'block-menu-copy-block',
|
|
75
|
+
parent: {
|
|
76
|
+
type: 'block-menu-section',
|
|
77
|
+
key: 'block-menu-section-copy',
|
|
78
|
+
rank: 200
|
|
79
|
+
},
|
|
80
|
+
component: function component() {
|
|
81
|
+
return /*#__PURE__*/_react.default.createElement(_copyBlock.default, {
|
|
82
|
+
api: api
|
|
83
|
+
});
|
|
84
|
+
}
|
|
71
85
|
}, {
|
|
72
86
|
type: 'block-menu-section',
|
|
73
|
-
key: 'block-menu-section-
|
|
87
|
+
key: 'block-menu-section-move-up-down',
|
|
74
88
|
rank: 300,
|
|
75
89
|
component: function component(_ref3) {
|
|
76
90
|
var children = _ref3.children;
|
|
@@ -78,6 +92,16 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
|
|
|
78
92
|
hasSeparator: true
|
|
79
93
|
}, children);
|
|
80
94
|
}
|
|
95
|
+
}, {
|
|
96
|
+
type: 'block-menu-section',
|
|
97
|
+
key: 'block-menu-section-delete',
|
|
98
|
+
rank: 400,
|
|
99
|
+
component: function component(_ref4) {
|
|
100
|
+
var children = _ref4.children;
|
|
101
|
+
return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
|
|
102
|
+
hasSeparator: true
|
|
103
|
+
}, children);
|
|
104
|
+
}
|
|
81
105
|
}, {
|
|
82
106
|
type: 'block-menu-nested',
|
|
83
107
|
key: 'nested-menu',
|
|
@@ -23,6 +23,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
23
23
|
var styles = {
|
|
24
24
|
base: "_2rkoglpi _bfhk1bhr _16qs1cd0"
|
|
25
25
|
};
|
|
26
|
+
var DEFAULT_MENU_WIDTH = 230;
|
|
26
27
|
var DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
27
28
|
var PopupWithListeners = (0, _uiReact.withReactEditorViewOuterListeners)(_ui.Popup);
|
|
28
29
|
var BlockMenuContent = function BlockMenuContent(_ref) {
|
|
@@ -106,8 +107,9 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
106
107
|
var targetHandleRef = editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(_styles.DRAG_HANDLE_SELECTOR);
|
|
107
108
|
if (targetHandleRef instanceof HTMLElement) {
|
|
108
109
|
return /*#__PURE__*/_react.default.createElement(PopupWithListeners, {
|
|
109
|
-
alignX: '
|
|
110
|
-
alignY: 'start'
|
|
110
|
+
alignX: 'right',
|
|
111
|
+
alignY: 'start' // respected when forcePlacement is true
|
|
112
|
+
,
|
|
111
113
|
handleClickOutside: closeMenu,
|
|
112
114
|
handleEscapeKeydown: closeMenu,
|
|
113
115
|
mountTo: mountTo,
|
|
@@ -115,7 +117,10 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
115
117
|
scrollableElement: scrollableElement,
|
|
116
118
|
target: targetHandleRef,
|
|
117
119
|
zIndex: _editorSharedStyles.akEditorFloatingOverlapPanelZIndex,
|
|
120
|
+
fitWidth: DEFAULT_MENU_WIDTH,
|
|
118
121
|
forcePlacement: true,
|
|
122
|
+
preventOverflow: true // disables forced horizontal placement when forcePlacement is on, so fitWidth controls flipping
|
|
123
|
+
,
|
|
119
124
|
stick: true,
|
|
120
125
|
offset: [_styles.DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
121
126
|
}, /*#__PURE__*/_react.default.createElement(BlockMenuContent, {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _reactIntlNext = require("react-intl-next");
|
|
10
|
+
var _blockMenu = require("@atlaskit/editor-common/block-menu");
|
|
11
|
+
var _clipboard = require("@atlaskit/editor-common/clipboard");
|
|
12
|
+
var _copyButton = require("@atlaskit/editor-common/copy-button");
|
|
13
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
14
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
15
|
+
var _utils = require("@atlaskit/editor-tables/utils");
|
|
16
|
+
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
17
|
+
var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy"));
|
|
18
|
+
var toDOMFromFragment = function toDOMFromFragment(fragment, schema) {
|
|
19
|
+
return _model.DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
20
|
+
};
|
|
21
|
+
var CopyBlockMenuItem = function CopyBlockMenuItem(_ref) {
|
|
22
|
+
var api = _ref.api;
|
|
23
|
+
var _useIntl = (0, _reactIntlNext.useIntl)(),
|
|
24
|
+
formatMessage = _useIntl.formatMessage;
|
|
25
|
+
var copyHandler = function copyHandler(event) {
|
|
26
|
+
var _api$selection;
|
|
27
|
+
// prevent click event from bubbling up to the ancestor elements
|
|
28
|
+
event.stopPropagation();
|
|
29
|
+
// get the current selection
|
|
30
|
+
var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
|
|
31
|
+
if (selection) {
|
|
32
|
+
var schema = selection.$from.doc.type.schema;
|
|
33
|
+
// for texts and inline nodes
|
|
34
|
+
if (selection instanceof _state.TextSelection) {
|
|
35
|
+
var _fragment;
|
|
36
|
+
var fragment = selection === null || selection === void 0 ? void 0 : selection.content().content;
|
|
37
|
+
if (!fragment) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// if text is inside of a layout column, the selection contains the layoutSection and layoutColumn for some reason
|
|
41
|
+
// But the layoutSection only contains the layoutColumn that the selected text is in, hence we can use the .firstChild
|
|
42
|
+
if ((_fragment = fragment) !== null && _fragment !== void 0 && _fragment.firstChild && fragment.firstChild.type.name === 'layoutSection') {
|
|
43
|
+
var layoutSectionNode = fragment.firstChild;
|
|
44
|
+
var layoutColumnNode = layoutSectionNode.firstChild;
|
|
45
|
+
var layoutContent = layoutColumnNode === null || layoutColumnNode === void 0 ? void 0 : layoutColumnNode.firstChild;
|
|
46
|
+
fragment = (layoutContent === null || layoutContent === void 0 ? void 0 : layoutContent.content) || _model.Fragment.empty;
|
|
47
|
+
}
|
|
48
|
+
var domNode = toDOMFromFragment(fragment, schema);
|
|
49
|
+
var div = document.createElement('div');
|
|
50
|
+
div.appendChild(domNode);
|
|
51
|
+
(0, _clipboard.copyHTMLToClipboard)(div);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// for table
|
|
55
|
+
if ((0, _utils.isTableSelected)(selection)) {
|
|
56
|
+
var nodeType = schema.nodes.table;
|
|
57
|
+
var tableNode = selection.$anchorCell.node(-1);
|
|
58
|
+
if (!tableNode) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
var _domNode = (0, _copyButton.toDOM)(tableNode, schema);
|
|
62
|
+
(0, _copyButton.copyDomNode)(_domNode, nodeType, selection);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// for other nodes
|
|
66
|
+
if (selection instanceof _state.NodeSelection) {
|
|
67
|
+
var _nodeType = selection.node.type;
|
|
68
|
+
var _domNode2 = (0, _copyButton.toDOM)(selection.node, schema);
|
|
69
|
+
(0, _copyButton.copyDomNode)(_domNode2, _nodeType, selection);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItem, {
|
|
74
|
+
elemBefore: /*#__PURE__*/_react.default.createElement(_copy.default, {
|
|
75
|
+
label: ""
|
|
76
|
+
}),
|
|
77
|
+
onClick: function onClick(e) {
|
|
78
|
+
return copyHandler(e);
|
|
79
|
+
}
|
|
80
|
+
}, formatMessage(_blockMenu.messages.copyBlock));
|
|
81
|
+
};
|
|
82
|
+
var _default = exports.default = (0, _reactIntlNext.injectIntl)(CopyBlockMenuItem);
|
|
@@ -6,6 +6,7 @@ import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
|
6
6
|
import DeleteIcon from '@atlaskit/icon/core/delete';
|
|
7
7
|
import ListBulletedIcon from '@atlaskit/icon/core/list-bulleted';
|
|
8
8
|
import TaskIcon from '@atlaskit/icon/core/task';
|
|
9
|
+
import CopyBlockMenuItem from './copy-block';
|
|
9
10
|
import { MoveDownDropdownItem } from './move-down';
|
|
10
11
|
import { MoveUpDropdownItem } from './move-up';
|
|
11
12
|
const getMoveUpMoveDownMenuComponents = api => {
|
|
@@ -49,7 +50,7 @@ export const getBlockMenuComponents = api => {
|
|
|
49
50
|
}
|
|
50
51
|
}, {
|
|
51
52
|
type: 'block-menu-section',
|
|
52
|
-
key: 'block-menu-section-
|
|
53
|
+
key: 'block-menu-section-copy',
|
|
53
54
|
rank: 200,
|
|
54
55
|
component: ({
|
|
55
56
|
children
|
|
@@ -58,9 +59,22 @@ export const getBlockMenuComponents = api => {
|
|
|
58
59
|
hasSeparator: true
|
|
59
60
|
}, children);
|
|
60
61
|
}
|
|
62
|
+
}, {
|
|
63
|
+
type: 'block-menu-item',
|
|
64
|
+
key: 'block-menu-copy-block',
|
|
65
|
+
parent: {
|
|
66
|
+
type: 'block-menu-section',
|
|
67
|
+
key: 'block-menu-section-copy',
|
|
68
|
+
rank: 200
|
|
69
|
+
},
|
|
70
|
+
component: () => {
|
|
71
|
+
return /*#__PURE__*/React.createElement(CopyBlockMenuItem, {
|
|
72
|
+
api: api
|
|
73
|
+
});
|
|
74
|
+
}
|
|
61
75
|
}, {
|
|
62
76
|
type: 'block-menu-section',
|
|
63
|
-
key: 'block-menu-section-
|
|
77
|
+
key: 'block-menu-section-move-up-down',
|
|
64
78
|
rank: 300,
|
|
65
79
|
component: ({
|
|
66
80
|
children
|
|
@@ -69,6 +83,17 @@ export const getBlockMenuComponents = api => {
|
|
|
69
83
|
hasSeparator: true
|
|
70
84
|
}, children);
|
|
71
85
|
}
|
|
86
|
+
}, {
|
|
87
|
+
type: 'block-menu-section',
|
|
88
|
+
key: 'block-menu-section-delete',
|
|
89
|
+
rank: 400,
|
|
90
|
+
component: ({
|
|
91
|
+
children
|
|
92
|
+
}) => {
|
|
93
|
+
return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
|
|
94
|
+
hasSeparator: true
|
|
95
|
+
}, children);
|
|
96
|
+
}
|
|
72
97
|
}, {
|
|
73
98
|
type: 'block-menu-nested',
|
|
74
99
|
key: 'nested-menu',
|
|
@@ -15,6 +15,7 @@ import { BlockMenuRenderer } from './block-menu-renderer';
|
|
|
15
15
|
const styles = {
|
|
16
16
|
base: "_2rkoglpi _bfhk1bhr _16qs1cd0"
|
|
17
17
|
};
|
|
18
|
+
const DEFAULT_MENU_WIDTH = 230;
|
|
18
19
|
const DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
19
20
|
const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
|
|
20
21
|
const BlockMenuContent = ({
|
|
@@ -96,8 +97,9 @@ const BlockMenu = ({
|
|
|
96
97
|
const targetHandleRef = editorView === null || editorView === void 0 ? void 0 : (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
|
|
97
98
|
if (targetHandleRef instanceof HTMLElement) {
|
|
98
99
|
return /*#__PURE__*/React.createElement(PopupWithListeners, {
|
|
99
|
-
alignX: '
|
|
100
|
-
alignY: 'start'
|
|
100
|
+
alignX: 'right',
|
|
101
|
+
alignY: 'start' // respected when forcePlacement is true
|
|
102
|
+
,
|
|
101
103
|
handleClickOutside: closeMenu,
|
|
102
104
|
handleEscapeKeydown: closeMenu,
|
|
103
105
|
mountTo: mountTo,
|
|
@@ -105,7 +107,10 @@ const BlockMenu = ({
|
|
|
105
107
|
scrollableElement: scrollableElement,
|
|
106
108
|
target: targetHandleRef,
|
|
107
109
|
zIndex: akEditorFloatingOverlapPanelZIndex,
|
|
110
|
+
fitWidth: DEFAULT_MENU_WIDTH,
|
|
108
111
|
forcePlacement: true,
|
|
112
|
+
preventOverflow: true // disables forced horizontal placement when forcePlacement is on, so fitWidth controls flipping
|
|
113
|
+
,
|
|
109
114
|
stick: true,
|
|
110
115
|
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
111
116
|
}, /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { injectIntl, useIntl } from 'react-intl-next';
|
|
3
|
+
import { messages } from '@atlaskit/editor-common/block-menu';
|
|
4
|
+
import { copyHTMLToClipboard } from '@atlaskit/editor-common/clipboard';
|
|
5
|
+
import { toDOM, copyDomNode } from '@atlaskit/editor-common/copy-button';
|
|
6
|
+
import { Fragment, DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
7
|
+
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
9
|
+
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
10
|
+
import CopyIcon from '@atlaskit/icon/core/copy';
|
|
11
|
+
const toDOMFromFragment = (fragment, schema) => {
|
|
12
|
+
return DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
13
|
+
};
|
|
14
|
+
const CopyBlockMenuItem = ({
|
|
15
|
+
api
|
|
16
|
+
}) => {
|
|
17
|
+
const {
|
|
18
|
+
formatMessage
|
|
19
|
+
} = useIntl();
|
|
20
|
+
const copyHandler = event => {
|
|
21
|
+
var _api$selection, _api$selection$shared, _api$selection$shared2;
|
|
22
|
+
// prevent click event from bubbling up to the ancestor elements
|
|
23
|
+
event.stopPropagation();
|
|
24
|
+
// get the current selection
|
|
25
|
+
const selection = api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : (_api$selection$shared = _api$selection.sharedState) === null || _api$selection$shared === void 0 ? void 0 : (_api$selection$shared2 = _api$selection$shared.currentState()) === null || _api$selection$shared2 === void 0 ? void 0 : _api$selection$shared2.selection;
|
|
26
|
+
if (selection) {
|
|
27
|
+
const schema = selection.$from.doc.type.schema;
|
|
28
|
+
// for texts and inline nodes
|
|
29
|
+
if (selection instanceof TextSelection) {
|
|
30
|
+
var _fragment;
|
|
31
|
+
let fragment = selection === null || selection === void 0 ? void 0 : selection.content().content;
|
|
32
|
+
if (!fragment) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// if text is inside of a layout column, the selection contains the layoutSection and layoutColumn for some reason
|
|
36
|
+
// But the layoutSection only contains the layoutColumn that the selected text is in, hence we can use the .firstChild
|
|
37
|
+
if ((_fragment = fragment) !== null && _fragment !== void 0 && _fragment.firstChild && fragment.firstChild.type.name === 'layoutSection') {
|
|
38
|
+
const layoutSectionNode = fragment.firstChild;
|
|
39
|
+
const layoutColumnNode = layoutSectionNode.firstChild;
|
|
40
|
+
const layoutContent = layoutColumnNode === null || layoutColumnNode === void 0 ? void 0 : layoutColumnNode.firstChild;
|
|
41
|
+
fragment = (layoutContent === null || layoutContent === void 0 ? void 0 : layoutContent.content) || Fragment.empty;
|
|
42
|
+
}
|
|
43
|
+
const domNode = toDOMFromFragment(fragment, schema);
|
|
44
|
+
const div = document.createElement('div');
|
|
45
|
+
div.appendChild(domNode);
|
|
46
|
+
copyHTMLToClipboard(div);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// for table
|
|
50
|
+
if (isTableSelected(selection)) {
|
|
51
|
+
const nodeType = schema.nodes.table;
|
|
52
|
+
const tableNode = selection.$anchorCell.node(-1);
|
|
53
|
+
if (!tableNode) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const domNode = toDOM(tableNode, schema);
|
|
57
|
+
copyDomNode(domNode, nodeType, selection);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// for other nodes
|
|
61
|
+
if (selection instanceof NodeSelection) {
|
|
62
|
+
const nodeType = selection.node.type;
|
|
63
|
+
const domNode = toDOM(selection.node, schema);
|
|
64
|
+
copyDomNode(domNode, nodeType, selection);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
|
|
69
|
+
elemBefore: /*#__PURE__*/React.createElement(CopyIcon, {
|
|
70
|
+
label: ""
|
|
71
|
+
}),
|
|
72
|
+
onClick: e => copyHandler(e)
|
|
73
|
+
}, formatMessage(messages.copyBlock));
|
|
74
|
+
};
|
|
75
|
+
export default injectIntl(CopyBlockMenuItem);
|
|
@@ -7,6 +7,7 @@ import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
|
7
7
|
import DeleteIcon from '@atlaskit/icon/core/delete';
|
|
8
8
|
import ListBulletedIcon from '@atlaskit/icon/core/list-bulleted';
|
|
9
9
|
import TaskIcon from '@atlaskit/icon/core/task';
|
|
10
|
+
import CopyBlockMenuItem from './copy-block';
|
|
10
11
|
import { MoveDownDropdownItem } from './move-down';
|
|
11
12
|
import { MoveUpDropdownItem } from './move-up';
|
|
12
13
|
var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(api) {
|
|
@@ -53,7 +54,7 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
|
|
|
53
54
|
}
|
|
54
55
|
}, {
|
|
55
56
|
type: 'block-menu-section',
|
|
56
|
-
key: 'block-menu-section-
|
|
57
|
+
key: 'block-menu-section-copy',
|
|
57
58
|
rank: 200,
|
|
58
59
|
component: function component(_ref2) {
|
|
59
60
|
var children = _ref2.children;
|
|
@@ -61,9 +62,22 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
|
|
|
61
62
|
hasSeparator: true
|
|
62
63
|
}, children);
|
|
63
64
|
}
|
|
65
|
+
}, {
|
|
66
|
+
type: 'block-menu-item',
|
|
67
|
+
key: 'block-menu-copy-block',
|
|
68
|
+
parent: {
|
|
69
|
+
type: 'block-menu-section',
|
|
70
|
+
key: 'block-menu-section-copy',
|
|
71
|
+
rank: 200
|
|
72
|
+
},
|
|
73
|
+
component: function component() {
|
|
74
|
+
return /*#__PURE__*/React.createElement(CopyBlockMenuItem, {
|
|
75
|
+
api: api
|
|
76
|
+
});
|
|
77
|
+
}
|
|
64
78
|
}, {
|
|
65
79
|
type: 'block-menu-section',
|
|
66
|
-
key: 'block-menu-section-
|
|
80
|
+
key: 'block-menu-section-move-up-down',
|
|
67
81
|
rank: 300,
|
|
68
82
|
component: function component(_ref3) {
|
|
69
83
|
var children = _ref3.children;
|
|
@@ -71,6 +85,16 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
|
|
|
71
85
|
hasSeparator: true
|
|
72
86
|
}, children);
|
|
73
87
|
}
|
|
88
|
+
}, {
|
|
89
|
+
type: 'block-menu-section',
|
|
90
|
+
key: 'block-menu-section-delete',
|
|
91
|
+
rank: 400,
|
|
92
|
+
component: function component(_ref4) {
|
|
93
|
+
var children = _ref4.children;
|
|
94
|
+
return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
|
|
95
|
+
hasSeparator: true
|
|
96
|
+
}, children);
|
|
97
|
+
}
|
|
74
98
|
}, {
|
|
75
99
|
type: 'block-menu-nested',
|
|
76
100
|
key: 'nested-menu',
|
|
@@ -15,6 +15,7 @@ import { BlockMenuRenderer } from './block-menu-renderer';
|
|
|
15
15
|
var styles = {
|
|
16
16
|
base: "_2rkoglpi _bfhk1bhr _16qs1cd0"
|
|
17
17
|
};
|
|
18
|
+
var DEFAULT_MENU_WIDTH = 230;
|
|
18
19
|
var DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
19
20
|
var PopupWithListeners = withReactEditorViewOuterListeners(Popup);
|
|
20
21
|
var BlockMenuContent = function BlockMenuContent(_ref) {
|
|
@@ -98,8 +99,9 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
98
99
|
var targetHandleRef = editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
|
|
99
100
|
if (targetHandleRef instanceof HTMLElement) {
|
|
100
101
|
return /*#__PURE__*/React.createElement(PopupWithListeners, {
|
|
101
|
-
alignX: '
|
|
102
|
-
alignY: 'start'
|
|
102
|
+
alignX: 'right',
|
|
103
|
+
alignY: 'start' // respected when forcePlacement is true
|
|
104
|
+
,
|
|
103
105
|
handleClickOutside: closeMenu,
|
|
104
106
|
handleEscapeKeydown: closeMenu,
|
|
105
107
|
mountTo: mountTo,
|
|
@@ -107,7 +109,10 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
107
109
|
scrollableElement: scrollableElement,
|
|
108
110
|
target: targetHandleRef,
|
|
109
111
|
zIndex: akEditorFloatingOverlapPanelZIndex,
|
|
112
|
+
fitWidth: DEFAULT_MENU_WIDTH,
|
|
110
113
|
forcePlacement: true,
|
|
114
|
+
preventOverflow: true // disables forced horizontal placement when forcePlacement is on, so fitWidth controls flipping
|
|
115
|
+
,
|
|
111
116
|
stick: true,
|
|
112
117
|
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
113
118
|
}, /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { injectIntl, useIntl } from 'react-intl-next';
|
|
3
|
+
import { messages } from '@atlaskit/editor-common/block-menu';
|
|
4
|
+
import { copyHTMLToClipboard } from '@atlaskit/editor-common/clipboard';
|
|
5
|
+
import { toDOM, copyDomNode } from '@atlaskit/editor-common/copy-button';
|
|
6
|
+
import { Fragment, DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
7
|
+
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
9
|
+
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
10
|
+
import CopyIcon from '@atlaskit/icon/core/copy';
|
|
11
|
+
var toDOMFromFragment = function toDOMFromFragment(fragment, schema) {
|
|
12
|
+
return DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
13
|
+
};
|
|
14
|
+
var CopyBlockMenuItem = function CopyBlockMenuItem(_ref) {
|
|
15
|
+
var api = _ref.api;
|
|
16
|
+
var _useIntl = useIntl(),
|
|
17
|
+
formatMessage = _useIntl.formatMessage;
|
|
18
|
+
var copyHandler = function copyHandler(event) {
|
|
19
|
+
var _api$selection;
|
|
20
|
+
// prevent click event from bubbling up to the ancestor elements
|
|
21
|
+
event.stopPropagation();
|
|
22
|
+
// get the current selection
|
|
23
|
+
var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
|
|
24
|
+
if (selection) {
|
|
25
|
+
var schema = selection.$from.doc.type.schema;
|
|
26
|
+
// for texts and inline nodes
|
|
27
|
+
if (selection instanceof TextSelection) {
|
|
28
|
+
var _fragment;
|
|
29
|
+
var fragment = selection === null || selection === void 0 ? void 0 : selection.content().content;
|
|
30
|
+
if (!fragment) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// if text is inside of a layout column, the selection contains the layoutSection and layoutColumn for some reason
|
|
34
|
+
// But the layoutSection only contains the layoutColumn that the selected text is in, hence we can use the .firstChild
|
|
35
|
+
if ((_fragment = fragment) !== null && _fragment !== void 0 && _fragment.firstChild && fragment.firstChild.type.name === 'layoutSection') {
|
|
36
|
+
var layoutSectionNode = fragment.firstChild;
|
|
37
|
+
var layoutColumnNode = layoutSectionNode.firstChild;
|
|
38
|
+
var layoutContent = layoutColumnNode === null || layoutColumnNode === void 0 ? void 0 : layoutColumnNode.firstChild;
|
|
39
|
+
fragment = (layoutContent === null || layoutContent === void 0 ? void 0 : layoutContent.content) || Fragment.empty;
|
|
40
|
+
}
|
|
41
|
+
var domNode = toDOMFromFragment(fragment, schema);
|
|
42
|
+
var div = document.createElement('div');
|
|
43
|
+
div.appendChild(domNode);
|
|
44
|
+
copyHTMLToClipboard(div);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// for table
|
|
48
|
+
if (isTableSelected(selection)) {
|
|
49
|
+
var nodeType = schema.nodes.table;
|
|
50
|
+
var tableNode = selection.$anchorCell.node(-1);
|
|
51
|
+
if (!tableNode) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
var _domNode = toDOM(tableNode, schema);
|
|
55
|
+
copyDomNode(_domNode, nodeType, selection);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// for other nodes
|
|
59
|
+
if (selection instanceof NodeSelection) {
|
|
60
|
+
var _nodeType = selection.node.type;
|
|
61
|
+
var _domNode2 = toDOM(selection.node, schema);
|
|
62
|
+
copyDomNode(_domNode2, _nodeType, selection);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
|
|
67
|
+
elemBefore: /*#__PURE__*/React.createElement(CopyIcon, {
|
|
68
|
+
label: ""
|
|
69
|
+
}),
|
|
70
|
+
onClick: function onClick(e) {
|
|
71
|
+
return copyHandler(e);
|
|
72
|
+
}
|
|
73
|
+
}, formatMessage(messages.copyBlock));
|
|
74
|
+
};
|
|
75
|
+
export default injectIntl(CopyBlockMenuItem);
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls';
|
|
3
|
+
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
3
4
|
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
|
|
4
5
|
export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
|
|
5
|
-
dependencies: [
|
|
6
|
+
dependencies: [
|
|
7
|
+
OptionalPlugin<BlockControlsPlugin>,
|
|
8
|
+
OptionalPlugin<UserIntentPlugin>,
|
|
9
|
+
OptionalPlugin<SelectionPlugin>
|
|
10
|
+
];
|
|
6
11
|
actions: {
|
|
7
12
|
registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
|
|
8
13
|
getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { WrappedComponentProps } from 'react-intl-next';
|
|
3
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
5
|
+
interface CopyBlockMenuItemProps {
|
|
6
|
+
api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: React.FC<import("react-intl-next").WithIntlProps<CopyBlockMenuItemProps & WrappedComponentProps>> & {
|
|
9
|
+
WrappedComponent: React.ComponentType<CopyBlockMenuItemProps & WrappedComponentProps>;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls';
|
|
3
|
+
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
3
4
|
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
|
|
4
5
|
export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
|
|
5
6
|
dependencies: [
|
|
6
7
|
OptionalPlugin<BlockControlsPlugin>,
|
|
7
|
-
OptionalPlugin<UserIntentPlugin
|
|
8
|
+
OptionalPlugin<UserIntentPlugin>,
|
|
9
|
+
OptionalPlugin<SelectionPlugin>
|
|
8
10
|
];
|
|
9
11
|
actions: {
|
|
10
12
|
registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { WrappedComponentProps } from 'react-intl-next';
|
|
3
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
5
|
+
interface CopyBlockMenuItemProps {
|
|
6
|
+
api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: React.FC<import("react-intl-next").WithIntlProps<CopyBlockMenuItemProps & WrappedComponentProps>> & {
|
|
9
|
+
WrappedComponent: React.ComponentType<CopyBlockMenuItemProps & WrappedComponentProps>;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "BlockMenu plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@atlaskit/editor-shared-styles": "^3.6.0",
|
|
40
40
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
41
41
|
"@atlaskit/editor-toolbar": "^0.3.0",
|
|
42
|
-
"@atlaskit/icon": "^
|
|
42
|
+
"@atlaskit/icon": "^28.0.0",
|
|
43
43
|
"@atlaskit/icon-lab": "^5.6.0",
|
|
44
44
|
"@atlaskit/primitives": "^14.11.0",
|
|
45
45
|
"@atlaskit/tokens": "^6.0.0",
|