@atlaskit/editor-plugin-block-menu 0.0.7 → 0.0.9

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 0.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - [`9155252ad4c00`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9155252ad4c00) -
8
+ [ux] copy link to the selected node in block menu
9
+ - Updated dependencies
10
+
11
+ ## 0.0.8
12
+
13
+ ### Patch Changes
14
+
15
+ - [`1bed58ba517b7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1bed58ba517b7) -
16
+ [ux] BlockMenu will be opened to the left or the drag handle by default and to the right when
17
+ there is no enough space.
18
+
3
19
  ## 0.0.7
4
20
 
5
21
  ### Patch Changes
@@ -11,9 +11,13 @@ var _main = require("./pm-plugins/main");
11
11
  var _blockMenu = _interopRequireDefault(require("./ui/block-menu"));
12
12
  var _blockMenuComponents = require("./ui/block-menu-components");
13
13
  var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
14
- var api = _ref.api;
14
+ var api = _ref.api,
15
+ config = _ref.config;
15
16
  var registry = (0, _editorActions.createBlockMenuRegistry)();
16
- registry.register((0, _blockMenuComponents.getBlockMenuComponents)(api));
17
+ registry.register((0, _blockMenuComponents.getBlockMenuComponents)({
18
+ api: api,
19
+ config: config
20
+ }));
17
21
  return {
18
22
  name: 'blockMenu',
19
23
  pmPlugins: function pmPlugins() {
@@ -8,13 +8,13 @@ exports.getBlockMenuComponents = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _react = _interopRequireDefault(require("react"));
10
10
  var _editorToolbar = require("@atlaskit/editor-toolbar");
11
- var _jira = _interopRequireDefault(require("@atlaskit/icon-lab/core/jira"));
12
11
  var _changes = _interopRequireDefault(require("@atlaskit/icon/core/changes"));
13
12
  var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
14
13
  var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete"));
15
14
  var _listBulleted = _interopRequireDefault(require("@atlaskit/icon/core/list-bulleted"));
16
15
  var _task = _interopRequireDefault(require("@atlaskit/icon/core/task"));
17
16
  var _copyBlock = _interopRequireDefault(require("./copy-block"));
17
+ var _copyLink = require("./copy-link");
18
18
  var _moveDown = require("./move-down");
19
19
  var _moveUp = require("./move-up");
20
20
  var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(api) {
@@ -50,21 +50,23 @@ var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(a
50
50
  }
51
51
  }];
52
52
  };
53
- var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockMenuComponents(api) {
53
+ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockMenuComponents(_ref) {
54
+ var api = _ref.api,
55
+ config = _ref.config;
54
56
  return [{
55
57
  type: 'block-menu-section',
56
58
  key: 'block-menu-section-format',
57
59
  rank: 100,
58
- component: function component(_ref) {
59
- var children = _ref.children;
60
+ component: function component(_ref2) {
61
+ var children = _ref2.children;
60
62
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, null, children);
61
63
  }
62
64
  }, {
63
65
  type: 'block-menu-section',
64
66
  key: 'block-menu-section-copy',
65
67
  rank: 200,
66
- component: function component(_ref2) {
67
- var children = _ref2.children;
68
+ component: function component(_ref3) {
69
+ var children = _ref3.children;
68
70
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
69
71
  hasSeparator: true
70
72
  }, children);
@@ -82,12 +84,26 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
82
84
  api: api
83
85
  });
84
86
  }
87
+ }, {
88
+ type: 'block-menu-item',
89
+ key: 'block-menu-item-copy-link',
90
+ parent: {
91
+ type: 'block-menu-section',
92
+ key: 'block-menu-section-copy',
93
+ rank: 100
94
+ },
95
+ component: function component() {
96
+ return /*#__PURE__*/_react.default.createElement(_copyLink.CopyLinkDropdownItem, {
97
+ api: api,
98
+ config: config
99
+ });
100
+ }
85
101
  }, {
86
102
  type: 'block-menu-section',
87
103
  key: 'block-menu-section-move-up-down',
88
104
  rank: 300,
89
- component: function component(_ref3) {
90
- var children = _ref3.children;
105
+ component: function component(_ref4) {
106
+ var children = _ref4.children;
91
107
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
92
108
  hasSeparator: true
93
109
  }, children);
@@ -96,8 +112,8 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
96
112
  type: 'block-menu-section',
97
113
  key: 'block-menu-section-delete',
98
114
  rank: 400,
99
- component: function component(_ref4) {
100
- var children = _ref4.children;
115
+ component: function component(_ref5) {
116
+ var children = _ref5.children;
101
117
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
102
118
  hasSeparator: true
103
119
  }, children);
@@ -129,21 +145,6 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
129
145
  })
130
146
  }, "Bullet list")));
131
147
  }
132
- }, {
133
- type: 'block-menu-item',
134
- key: 'block-menu-item-create-jira',
135
- parent: {
136
- type: 'block-menu-section',
137
- key: 'block-menu-section-format',
138
- rank: 200
139
- },
140
- component: function component() {
141
- return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItem, {
142
- elemBefore: /*#__PURE__*/_react.default.createElement(_jira.default, {
143
- label: ""
144
- })
145
- }, "Create Jira work item");
146
- }
147
148
  }].concat((0, _toConsumableArray2.default)(getMoveUpMoveDownMenuComponents(api)), [{
148
149
  type: 'block-menu-item',
149
150
  key: 'block-menu-item-delete',
@@ -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: 'left',
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,31 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.CopyLinkDropdownItem = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _reactIntlNext = require("react-intl-next");
11
+ var _messages = require("@atlaskit/editor-common/messages");
12
+ var _editorToolbar = require("@atlaskit/editor-toolbar");
13
+ var _link = _interopRequireDefault(require("@atlaskit/icon/core/link"));
14
+ var _copyLink = require("./utils/copyLink");
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
16
+ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
17
+ var api = _ref.api,
18
+ config = _ref.config;
19
+ var _useIntl = (0, _reactIntlNext.useIntl)(),
20
+ formatMessage = _useIntl.formatMessage;
21
+ var handleClick = (0, _react.useCallback)(function () {
22
+ return (0, _copyLink.copyLink)(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockQueryParam, api);
23
+ }, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockQueryParam, api]);
24
+ return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItem, {
25
+ onClick: handleClick,
26
+ elemBefore: /*#__PURE__*/_react.default.createElement(_link.default, {
27
+ label: ""
28
+ })
29
+ }, formatMessage(_messages.blockMenuMessages.copyLink));
30
+ };
31
+ var CopyLinkDropdownItem = exports.CopyLinkDropdownItem = (0, _reactIntlNext.injectIntl)(CopyLinkDropdownItemContent);
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.copyLink = void 0;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
10
+ var _clipboard = require("@atlaskit/editor-common/clipboard");
11
+ var _state = require("@atlaskit/editor-prosemirror/state");
12
+ var _editorTables = require("@atlaskit/editor-tables");
13
+ var copyLink = exports.copyLink = /*#__PURE__*/function () {
14
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(getLinkPath) {
15
+ var blockQueryParam,
16
+ api,
17
+ _api$selection,
18
+ node,
19
+ selection,
20
+ path,
21
+ url,
22
+ href,
23
+ _args = arguments;
24
+ return _regenerator.default.wrap(function _callee$(_context) {
25
+ while (1) switch (_context.prev = _context.next) {
26
+ case 0:
27
+ blockQueryParam = _args.length > 1 && _args[1] !== undefined ? _args[1] : 'block';
28
+ api = _args.length > 2 ? _args[2] : undefined;
29
+ _context.prev = 2;
30
+ selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
31
+ if (selection instanceof _state.NodeSelection && selection.node) {
32
+ node = selection.node;
33
+ } else if (selection instanceof _state.TextSelection) {
34
+ node = selection.$from.node();
35
+ } else if (selection instanceof _editorTables.CellSelection) {
36
+ node = selection.$anchorCell.node(-1);
37
+ }
38
+ if (!(!node || !node.attrs || !node.attrs.localId)) {
39
+ _context.next = 7;
40
+ break;
41
+ }
42
+ return _context.abrupt("return", false);
43
+ case 7:
44
+ path = (getLinkPath === null || getLinkPath === void 0 ? void 0 : getLinkPath()) || location.pathname;
45
+ if (path) {
46
+ _context.next = 10;
47
+ break;
48
+ }
49
+ return _context.abrupt("return", false);
50
+ case 10:
51
+ url = new URL(location.origin + path);
52
+ url.searchParams.set(blockQueryParam, node.attrs.localId);
53
+ href = url.toString();
54
+ _context.next = 15;
55
+ return (0, _clipboard.copyToClipboard)(href);
56
+ case 15:
57
+ return _context.abrupt("return", true);
58
+ case 18:
59
+ _context.prev = 18;
60
+ _context.t0 = _context["catch"](2);
61
+ return _context.abrupt("return", false);
62
+ case 21:
63
+ case "end":
64
+ return _context.stop();
65
+ }
66
+ }, _callee, null, [[2, 18]]);
67
+ }));
68
+ return function copyLink(_x) {
69
+ return _ref.apply(this, arguments);
70
+ };
71
+ }();
@@ -4,10 +4,14 @@ import { createPlugin } from './pm-plugins/main';
4
4
  import BlockMenu from './ui/block-menu';
5
5
  import { getBlockMenuComponents } from './ui/block-menu-components';
6
6
  export const blockMenuPlugin = ({
7
- api
7
+ api,
8
+ config
8
9
  }) => {
9
10
  const registry = createBlockMenuRegistry();
10
- registry.register(getBlockMenuComponents(api));
11
+ registry.register(getBlockMenuComponents({
12
+ api,
13
+ config
14
+ }));
11
15
  return {
12
16
  name: 'blockMenu',
13
17
  pmPlugins() {
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
2
  import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
3
- import JiraIcon from '@atlaskit/icon-lab/core/jira';
4
3
  import ChangesIcon from '@atlaskit/icon/core/changes';
5
4
  import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
6
5
  import DeleteIcon from '@atlaskit/icon/core/delete';
7
6
  import ListBulletedIcon from '@atlaskit/icon/core/list-bulleted';
8
7
  import TaskIcon from '@atlaskit/icon/core/task';
9
8
  import CopyBlockMenuItem from './copy-block';
9
+ import { CopyLinkDropdownItem } from './copy-link';
10
10
  import { MoveDownDropdownItem } from './move-down';
11
11
  import { MoveUpDropdownItem } from './move-up';
12
12
  const getMoveUpMoveDownMenuComponents = api => {
@@ -38,7 +38,10 @@ const getMoveUpMoveDownMenuComponents = api => {
38
38
  })
39
39
  }];
40
40
  };
41
- export const getBlockMenuComponents = api => {
41
+ export const getBlockMenuComponents = ({
42
+ api,
43
+ config
44
+ }) => {
42
45
  return [{
43
46
  type: 'block-menu-section',
44
47
  key: 'block-menu-section-format',
@@ -72,6 +75,18 @@ export const getBlockMenuComponents = api => {
72
75
  api: api
73
76
  });
74
77
  }
78
+ }, {
79
+ type: 'block-menu-item',
80
+ key: 'block-menu-item-copy-link',
81
+ parent: {
82
+ type: 'block-menu-section',
83
+ key: 'block-menu-section-copy',
84
+ rank: 100
85
+ },
86
+ component: () => /*#__PURE__*/React.createElement(CopyLinkDropdownItem, {
87
+ api: api,
88
+ config: config
89
+ })
75
90
  }, {
76
91
  type: 'block-menu-section',
77
92
  key: 'block-menu-section-move-up-down',
@@ -121,21 +136,6 @@ export const getBlockMenuComponents = api => {
121
136
  })
122
137
  }, "Bullet list")));
123
138
  }
124
- }, {
125
- type: 'block-menu-item',
126
- key: 'block-menu-item-create-jira',
127
- parent: {
128
- type: 'block-menu-section',
129
- key: 'block-menu-section-format',
130
- rank: 200
131
- },
132
- component: () => {
133
- return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
134
- elemBefore: /*#__PURE__*/React.createElement(JiraIcon, {
135
- label: ""
136
- })
137
- }, "Create Jira work item");
138
- }
139
139
  }, ...getMoveUpMoveDownMenuComponents(api), {
140
140
  type: 'block-menu-item',
141
141
  key: 'block-menu-item-delete',
@@ -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: 'left',
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,24 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useIntl, injectIntl } from 'react-intl-next';
3
+ import { blockMenuMessages as messages } from '@atlaskit/editor-common/messages';
4
+ import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
5
+ import LinkIcon from '@atlaskit/icon/core/link';
6
+ import { copyLink } from './utils/copyLink';
7
+ const CopyLinkDropdownItemContent = ({
8
+ api,
9
+ config
10
+ }) => {
11
+ const {
12
+ formatMessage
13
+ } = useIntl();
14
+ const handleClick = useCallback(() => {
15
+ return copyLink(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockQueryParam, api);
16
+ }, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockQueryParam, api]);
17
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
18
+ onClick: handleClick,
19
+ elemBefore: /*#__PURE__*/React.createElement(LinkIcon, {
20
+ label: ""
21
+ })
22
+ }, formatMessage(messages.copyLink));
23
+ };
24
+ export const CopyLinkDropdownItem = injectIntl(CopyLinkDropdownItemContent);
@@ -0,0 +1,31 @@
1
+ import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
2
+ import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
+ import { CellSelection } from '@atlaskit/editor-tables';
4
+ export const copyLink = async (getLinkPath, blockQueryParam = 'block', api) => {
5
+ try {
6
+ var _api$selection, _api$selection$shared;
7
+ let node;
8
+ 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.currentState()) === null || _api$selection$shared === void 0 ? void 0 : _api$selection$shared.selection;
9
+ if (selection instanceof NodeSelection && selection.node) {
10
+ node = selection.node;
11
+ } else if (selection instanceof TextSelection) {
12
+ node = selection.$from.node();
13
+ } else if (selection instanceof CellSelection) {
14
+ node = selection.$anchorCell.node(-1);
15
+ }
16
+ if (!node || !node.attrs || !node.attrs.localId) {
17
+ return false;
18
+ }
19
+ const path = (getLinkPath === null || getLinkPath === void 0 ? void 0 : getLinkPath()) || location.pathname;
20
+ if (!path) {
21
+ return false;
22
+ }
23
+ const url = new URL(location.origin + path);
24
+ url.searchParams.set(blockQueryParam, node.attrs.localId);
25
+ const href = url.toString();
26
+ await copyToClipboard(href);
27
+ return true;
28
+ } catch (e) {
29
+ return false;
30
+ }
31
+ };
@@ -4,9 +4,13 @@ import { createPlugin } from './pm-plugins/main';
4
4
  import BlockMenu from './ui/block-menu';
5
5
  import { getBlockMenuComponents } from './ui/block-menu-components';
6
6
  export var blockMenuPlugin = function blockMenuPlugin(_ref) {
7
- var api = _ref.api;
7
+ var api = _ref.api,
8
+ config = _ref.config;
8
9
  var registry = createBlockMenuRegistry();
9
- registry.register(getBlockMenuComponents(api));
10
+ registry.register(getBlockMenuComponents({
11
+ api: api,
12
+ config: config
13
+ }));
10
14
  return {
11
15
  name: 'blockMenu',
12
16
  pmPlugins: function pmPlugins() {
@@ -1,13 +1,13 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import React from 'react';
3
3
  import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
4
- import JiraIcon from '@atlaskit/icon-lab/core/jira';
5
4
  import ChangesIcon from '@atlaskit/icon/core/changes';
6
5
  import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
7
6
  import DeleteIcon from '@atlaskit/icon/core/delete';
8
7
  import ListBulletedIcon from '@atlaskit/icon/core/list-bulleted';
9
8
  import TaskIcon from '@atlaskit/icon/core/task';
10
9
  import CopyBlockMenuItem from './copy-block';
10
+ import { CopyLinkDropdownItem } from './copy-link';
11
11
  import { MoveDownDropdownItem } from './move-down';
12
12
  import { MoveUpDropdownItem } from './move-up';
13
13
  var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(api) {
@@ -43,21 +43,23 @@ var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(a
43
43
  }
44
44
  }];
45
45
  };
46
- export var getBlockMenuComponents = function getBlockMenuComponents(api) {
46
+ export var getBlockMenuComponents = function getBlockMenuComponents(_ref) {
47
+ var api = _ref.api,
48
+ config = _ref.config;
47
49
  return [{
48
50
  type: 'block-menu-section',
49
51
  key: 'block-menu-section-format',
50
52
  rank: 100,
51
- component: function component(_ref) {
52
- var children = _ref.children;
53
+ component: function component(_ref2) {
54
+ var children = _ref2.children;
53
55
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, null, children);
54
56
  }
55
57
  }, {
56
58
  type: 'block-menu-section',
57
59
  key: 'block-menu-section-copy',
58
60
  rank: 200,
59
- component: function component(_ref2) {
60
- var children = _ref2.children;
61
+ component: function component(_ref3) {
62
+ var children = _ref3.children;
61
63
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
62
64
  hasSeparator: true
63
65
  }, children);
@@ -75,12 +77,26 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
75
77
  api: api
76
78
  });
77
79
  }
80
+ }, {
81
+ type: 'block-menu-item',
82
+ key: 'block-menu-item-copy-link',
83
+ parent: {
84
+ type: 'block-menu-section',
85
+ key: 'block-menu-section-copy',
86
+ rank: 100
87
+ },
88
+ component: function component() {
89
+ return /*#__PURE__*/React.createElement(CopyLinkDropdownItem, {
90
+ api: api,
91
+ config: config
92
+ });
93
+ }
78
94
  }, {
79
95
  type: 'block-menu-section',
80
96
  key: 'block-menu-section-move-up-down',
81
97
  rank: 300,
82
- component: function component(_ref3) {
83
- var children = _ref3.children;
98
+ component: function component(_ref4) {
99
+ var children = _ref4.children;
84
100
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
85
101
  hasSeparator: true
86
102
  }, children);
@@ -89,8 +105,8 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
89
105
  type: 'block-menu-section',
90
106
  key: 'block-menu-section-delete',
91
107
  rank: 400,
92
- component: function component(_ref4) {
93
- var children = _ref4.children;
108
+ component: function component(_ref5) {
109
+ var children = _ref5.children;
94
110
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
95
111
  hasSeparator: true
96
112
  }, children);
@@ -122,21 +138,6 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
122
138
  })
123
139
  }, "Bullet list")));
124
140
  }
125
- }, {
126
- type: 'block-menu-item',
127
- key: 'block-menu-item-create-jira',
128
- parent: {
129
- type: 'block-menu-section',
130
- key: 'block-menu-section-format',
131
- rank: 200
132
- },
133
- component: function component() {
134
- return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
135
- elemBefore: /*#__PURE__*/React.createElement(JiraIcon, {
136
- label: ""
137
- })
138
- }, "Create Jira work item");
139
- }
140
141
  }].concat(_toConsumableArray(getMoveUpMoveDownMenuComponents(api)), [{
141
142
  type: 'block-menu-item',
142
143
  key: 'block-menu-item-delete',
@@ -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: 'left',
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,22 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useIntl, injectIntl } from 'react-intl-next';
3
+ import { blockMenuMessages as messages } from '@atlaskit/editor-common/messages';
4
+ import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
5
+ import LinkIcon from '@atlaskit/icon/core/link';
6
+ import { copyLink } from './utils/copyLink';
7
+ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
8
+ var api = _ref.api,
9
+ config = _ref.config;
10
+ var _useIntl = useIntl(),
11
+ formatMessage = _useIntl.formatMessage;
12
+ var handleClick = useCallback(function () {
13
+ return copyLink(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockQueryParam, api);
14
+ }, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockQueryParam, api]);
15
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
16
+ onClick: handleClick,
17
+ elemBefore: /*#__PURE__*/React.createElement(LinkIcon, {
18
+ label: ""
19
+ })
20
+ }, formatMessage(messages.copyLink));
21
+ };
22
+ export var CopyLinkDropdownItem = injectIntl(CopyLinkDropdownItemContent);
@@ -0,0 +1,64 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
4
+ import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
5
+ import { CellSelection } from '@atlaskit/editor-tables';
6
+ export var copyLink = /*#__PURE__*/function () {
7
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(getLinkPath) {
8
+ var blockQueryParam,
9
+ api,
10
+ _api$selection,
11
+ node,
12
+ selection,
13
+ path,
14
+ url,
15
+ href,
16
+ _args = arguments;
17
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
18
+ while (1) switch (_context.prev = _context.next) {
19
+ case 0:
20
+ blockQueryParam = _args.length > 1 && _args[1] !== undefined ? _args[1] : 'block';
21
+ api = _args.length > 2 ? _args[2] : undefined;
22
+ _context.prev = 2;
23
+ selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
24
+ if (selection instanceof NodeSelection && selection.node) {
25
+ node = selection.node;
26
+ } else if (selection instanceof TextSelection) {
27
+ node = selection.$from.node();
28
+ } else if (selection instanceof CellSelection) {
29
+ node = selection.$anchorCell.node(-1);
30
+ }
31
+ if (!(!node || !node.attrs || !node.attrs.localId)) {
32
+ _context.next = 7;
33
+ break;
34
+ }
35
+ return _context.abrupt("return", false);
36
+ case 7:
37
+ path = (getLinkPath === null || getLinkPath === void 0 ? void 0 : getLinkPath()) || location.pathname;
38
+ if (path) {
39
+ _context.next = 10;
40
+ break;
41
+ }
42
+ return _context.abrupt("return", false);
43
+ case 10:
44
+ url = new URL(location.origin + path);
45
+ url.searchParams.set(blockQueryParam, node.attrs.localId);
46
+ href = url.toString();
47
+ _context.next = 15;
48
+ return copyToClipboard(href);
49
+ case 15:
50
+ return _context.abrupt("return", true);
51
+ case 18:
52
+ _context.prev = 18;
53
+ _context.t0 = _context["catch"](2);
54
+ return _context.abrupt("return", false);
55
+ case 21:
56
+ case "end":
57
+ return _context.stop();
58
+ }
59
+ }, _callee, null, [[2, 18]]);
60
+ }));
61
+ return function copyLink(_x) {
62
+ return _ref.apply(this, arguments);
63
+ };
64
+ }();
@@ -8,11 +8,23 @@ export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
8
8
  OptionalPlugin<UserIntentPlugin>,
9
9
  OptionalPlugin<SelectionPlugin>
10
10
  ];
11
+ pluginConfiguration?: BlockMenuPluginOptions;
11
12
  actions: {
12
13
  registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
13
14
  getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
14
15
  };
15
16
  }>;
17
+ export type BlockMenuPluginOptions = {
18
+ /**
19
+ * Optional function to retrieve the current link path for the editor context.
20
+ * @returns The current link path as a string, or null if no path is available
21
+ */
22
+ getLinkPath?: () => string | null;
23
+ /**
24
+ * Optional query parameter name used for block-specific URL to create a deep link to specific block
25
+ */
26
+ blockQueryParam?: string;
27
+ };
16
28
  type WithRank<T> = T & {
17
29
  rank: number;
18
30
  };
@@ -1,2 +1,2 @@
1
1
  export { blockMenuPlugin } from './blockMenuPlugin';
2
- export type { BlockMenuPlugin, RegisterBlockMenuComponent, Parent } from './blockMenuPluginType';
2
+ export type { BlockMenuPlugin, RegisterBlockMenuComponent, Parent, BlockMenuPluginOptions, } from './blockMenuPluginType';
@@ -1,4 +1,7 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import type { BlockMenuPlugin } from '../blockMenuPluginType';
2
+ import type { BlockMenuPlugin, BlockMenuPluginOptions } from '../blockMenuPluginType';
3
3
  import { type RegisterBlockMenuComponent } from '../blockMenuPluginType';
4
- export declare const getBlockMenuComponents: (api: ExtractInjectionAPI<BlockMenuPlugin> | undefined) => RegisterBlockMenuComponent[];
4
+ export declare const getBlockMenuComponents: ({ api, config, }: {
5
+ api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
6
+ config: BlockMenuPluginOptions | undefined;
7
+ }) => RegisterBlockMenuComponent[];
@@ -0,0 +1,12 @@
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, BlockMenuPluginOptions } from '../blockMenuPluginType';
5
+ type Props = {
6
+ api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
7
+ config: BlockMenuPluginOptions | undefined;
8
+ };
9
+ export declare const CopyLinkDropdownItem: React.FC<import("react-intl-next").WithIntlProps<Props & WrappedComponentProps>> & {
10
+ WrappedComponent: React.ComponentType<Props & WrappedComponentProps>;
11
+ };
12
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { BlockMenuPlugin } from '../../blockMenuPluginType';
3
+ export declare const copyLink: (getLinkPath?: () => string | null, blockQueryParam?: string, api?: ExtractInjectionAPI<BlockMenuPlugin>) => Promise<boolean>;
@@ -8,11 +8,23 @@ export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
8
8
  OptionalPlugin<UserIntentPlugin>,
9
9
  OptionalPlugin<SelectionPlugin>
10
10
  ];
11
+ pluginConfiguration?: BlockMenuPluginOptions;
11
12
  actions: {
12
13
  registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
13
14
  getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
14
15
  };
15
16
  }>;
17
+ export type BlockMenuPluginOptions = {
18
+ /**
19
+ * Optional function to retrieve the current link path for the editor context.
20
+ * @returns The current link path as a string, or null if no path is available
21
+ */
22
+ getLinkPath?: () => string | null;
23
+ /**
24
+ * Optional query parameter name used for block-specific URL to create a deep link to specific block
25
+ */
26
+ blockQueryParam?: string;
27
+ };
16
28
  type WithRank<T> = T & {
17
29
  rank: number;
18
30
  };
@@ -1,2 +1,2 @@
1
1
  export { blockMenuPlugin } from './blockMenuPlugin';
2
- export type { BlockMenuPlugin, RegisterBlockMenuComponent, Parent } from './blockMenuPluginType';
2
+ export type { BlockMenuPlugin, RegisterBlockMenuComponent, Parent, BlockMenuPluginOptions, } from './blockMenuPluginType';
@@ -1,4 +1,7 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import type { BlockMenuPlugin } from '../blockMenuPluginType';
2
+ import type { BlockMenuPlugin, BlockMenuPluginOptions } from '../blockMenuPluginType';
3
3
  import { type RegisterBlockMenuComponent } from '../blockMenuPluginType';
4
- export declare const getBlockMenuComponents: (api: ExtractInjectionAPI<BlockMenuPlugin> | undefined) => RegisterBlockMenuComponent[];
4
+ export declare const getBlockMenuComponents: ({ api, config, }: {
5
+ api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
6
+ config: BlockMenuPluginOptions | undefined;
7
+ }) => RegisterBlockMenuComponent[];
@@ -0,0 +1,12 @@
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, BlockMenuPluginOptions } from '../blockMenuPluginType';
5
+ type Props = {
6
+ api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
7
+ config: BlockMenuPluginOptions | undefined;
8
+ };
9
+ export declare const CopyLinkDropdownItem: React.FC<import("react-intl-next").WithIntlProps<Props & WrappedComponentProps>> & {
10
+ WrappedComponent: React.ComponentType<Props & WrappedComponentProps>;
11
+ };
12
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { BlockMenuPlugin } from '../../blockMenuPluginType';
3
+ export declare const copyLink: (getLinkPath?: () => string | null, blockQueryParam?: string, api?: ExtractInjectionAPI<BlockMenuPlugin>) => Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -46,7 +46,7 @@
46
46
  "@babel/runtime": "^7.0.0"
47
47
  },
48
48
  "peerDependencies": {
49
- "@atlaskit/editor-common": "^107.26.0",
49
+ "@atlaskit/editor-common": "^107.28.0",
50
50
  "react": "^18.2.0",
51
51
  "react-intl-next": "npm:react-intl@^5.18.1"
52
52
  },