@atlaskit/editor-plugin-block-controls 1.1.0 → 1.2.0

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/plugin.js +30 -2
  3. package/dist/cjs/pm-plugins/decorations.js +50 -0
  4. package/dist/cjs/pm-plugins/main.js +66 -4
  5. package/dist/cjs/ui/consts.js +8 -0
  6. package/dist/cjs/ui/drag-handle-menu.js +15 -0
  7. package/dist/cjs/ui/drag-handle.js +99 -0
  8. package/dist/cjs/ui/drag-preview.js +35 -0
  9. package/dist/cjs/ui/drop-target.js +57 -0
  10. package/dist/cjs/ui/global-styles.js +19 -0
  11. package/dist/es2019/plugin.js +29 -3
  12. package/dist/es2019/pm-plugins/decorations.js +43 -0
  13. package/dist/es2019/pm-plugins/main.js +66 -5
  14. package/dist/es2019/ui/consts.js +2 -0
  15. package/dist/es2019/ui/drag-handle-menu.js +10 -0
  16. package/dist/es2019/ui/drag-handle.js +90 -0
  17. package/dist/es2019/ui/drag-preview.js +27 -0
  18. package/dist/es2019/ui/drop-target.js +39 -0
  19. package/dist/es2019/ui/global-styles.js +12 -0
  20. package/dist/esm/plugin.js +30 -3
  21. package/dist/esm/pm-plugins/decorations.js +43 -0
  22. package/dist/esm/pm-plugins/main.js +66 -4
  23. package/dist/esm/ui/consts.js +2 -0
  24. package/dist/esm/ui/drag-handle-menu.js +8 -0
  25. package/dist/esm/ui/drag-handle.js +92 -0
  26. package/dist/esm/ui/drag-preview.js +29 -0
  27. package/dist/esm/ui/drop-target.js +47 -0
  28. package/dist/esm/ui/global-styles.js +12 -0
  29. package/dist/types/pm-plugins/decorations.d.ts +6 -0
  30. package/dist/types/pm-plugins/main.d.ts +6 -3
  31. package/dist/types/types.d.ts +11 -2
  32. package/dist/types/ui/consts.d.ts +2 -0
  33. package/dist/types/ui/drag-handle-menu.d.ts +6 -0
  34. package/dist/types/ui/drag-handle.d.ts +9 -0
  35. package/dist/types/ui/drag-preview.d.ts +1 -0
  36. package/dist/types/ui/drop-target.d.ts +7 -0
  37. package/dist/types/ui/global-styles.d.ts +3 -0
  38. package/dist/types-ts4.5/pm-plugins/decorations.d.ts +6 -0
  39. package/dist/types-ts4.5/pm-plugins/main.d.ts +6 -3
  40. package/dist/types-ts4.5/types.d.ts +11 -2
  41. package/dist/types-ts4.5/ui/consts.d.ts +2 -0
  42. package/dist/types-ts4.5/ui/drag-handle-menu.d.ts +6 -0
  43. package/dist/types-ts4.5/ui/drag-handle.d.ts +9 -0
  44. package/dist/types-ts4.5/ui/drag-preview.d.ts +1 -0
  45. package/dist/types-ts4.5/ui/drop-target.d.ts +7 -0
  46. package/dist/types-ts4.5/ui/global-styles.d.ts +3 -0
  47. package/package.json +7 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#93512](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/93512) [`15155cd6eb61`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/15155cd6eb61) - add basic dnd behaviour to block controls plugin
8
+
3
9
  ## 1.1.0
4
10
 
5
11
  ### Minor Changes
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.blockControlsPlugin = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
7
9
  var _main = require("./pm-plugins/main");
10
+ var _dragHandleMenu = require("./ui/drag-handle-menu");
11
+ var _globalStyles = require("./ui/global-styles");
8
12
  var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPlugin(_ref) {
9
13
  var api = _ref.api;
10
14
  return {
@@ -17,8 +21,32 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
17
21
  }
18
22
  }];
19
23
  },
20
- getSharedState: function getSharedState(_editorState) {
21
- return undefined;
24
+ commands: {
25
+ moveNode: function moveNode(start, end, to) {
26
+ return function (_ref2) {
27
+ var _api$core;
28
+ var tr = _ref2.tr;
29
+ var node = tr.doc.content.cut(start, end); // cut the content
30
+ tr.delete(start, end); // delete the content from the original position
31
+ tr.insert(tr.mapping.map(to), node); // insert the content at the new position
32
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.focus();
33
+ return tr;
34
+ };
35
+ }
36
+ },
37
+ getSharedState: function getSharedState(editorState) {
38
+ var _key$getState$isMenuO, _key$getState;
39
+ if (!editorState) {
40
+ return undefined;
41
+ }
42
+ return {
43
+ isMenuOpen: (_key$getState$isMenuO = (_key$getState = _main.key.getState(editorState)) === null || _key$getState === void 0 ? void 0 : _key$getState.isMenuOpen) !== null && _key$getState$isMenuO !== void 0 ? _key$getState$isMenuO : false
44
+ };
45
+ },
46
+ contentComponent: function contentComponent() {
47
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_dragHandleMenu.DragHandleMenu, {
48
+ api: api
49
+ }), /*#__PURE__*/_react.default.createElement(_globalStyles.GlobalStylesWrapper, null));
22
50
  }
23
51
  };
24
52
  };
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.dropTargetDecorations = exports.dragHandleDecoration = void 0;
8
+ var _react = require("react");
9
+ var _reactDom = _interopRequireDefault(require("react-dom"));
10
+ var _view = require("@atlaskit/editor-prosemirror/view");
11
+ var _dragHandle = require("../ui/drag-handle");
12
+ var _dropTarget = require("../ui/drop-target");
13
+ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetDecorations(oldState, newState, api) {
14
+ var decorations = [];
15
+ oldState.doc.nodesBetween(0, newState.doc.nodeSize - 2, function (node, pos) {
16
+ decorations.push(_view.Decoration.widget(pos + node.nodeSize, function () {
17
+ var element = document.createElement('div');
18
+ _reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_dropTarget.DropTarget, {
19
+ api: api,
20
+ pos: pos + node.nodeSize
21
+ }), element);
22
+ return element;
23
+ }));
24
+ return false;
25
+ });
26
+ decorations.push(_view.Decoration.widget(0, function () {
27
+ var element = document.createElement('div');
28
+ _reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_dropTarget.DropTarget, {
29
+ api: api,
30
+ pos: 0
31
+ }), element);
32
+ return element;
33
+ }));
34
+ return decorations;
35
+ };
36
+ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDecoration(oldState,
37
+ // @ts-ignore
38
+ meta, api) {
39
+ return _view.DecorationSet.create(oldState.doc, [_view.Decoration.widget(meta.pos + meta.size, function (view, getPos) {
40
+ var element = document.createElement('div');
41
+ _reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_dragHandle.DragHandle, {
42
+ dom: meta.dom,
43
+ api: api,
44
+ start: meta.pos,
45
+ end: meta.pos + meta.size
46
+ }), element);
47
+ element.style.position = 'absolute';
48
+ return element;
49
+ })]);
50
+ };
@@ -7,6 +7,7 @@ exports.key = exports.createPlugin = void 0;
7
7
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
8
8
  var _state = require("@atlaskit/editor-prosemirror/state");
9
9
  var _view = require("@atlaskit/editor-prosemirror/view");
10
+ var _decorations = require("./decorations");
10
11
  var key = exports.key = new _state.PluginKey('blockControls');
11
12
  var createPlugin = exports.createPlugin = function createPlugin(api) {
12
13
  return new _safePlugin.SafePlugin({
@@ -14,13 +15,40 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
14
15
  state: {
15
16
  init: function init() {
16
17
  return {
17
- decorations: _view.DecorationSet.empty
18
+ decorations: _view.DecorationSet.empty,
19
+ activeNode: null,
20
+ isDragging: false,
21
+ isMenuOpen: false
18
22
  };
19
23
  },
20
- apply: function apply(tr, currentState) {
21
- var decorations = currentState.decorations;
24
+ apply: function apply(tr, currentState, oldState, newState) {
25
+ var _meta$isDragging;
26
+ var activeNode = currentState.activeNode,
27
+ decorations = currentState.decorations,
28
+ isMenuOpen = currentState.isMenuOpen;
29
+ var meta = tr.getMeta(key);
30
+ // Drag handle decoration
31
+ if (meta && meta.pos !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos) && api) {
32
+ decorations = (0, _decorations.dragHandleDecoration)(newState, meta, api);
33
+ }
34
+ // Drop target decorations
35
+ if (meta !== null && meta !== void 0 && meta.isDragging && api) {
36
+ decorations = _view.DecorationSet.create(newState.doc, []);
37
+ var decs = (0, _decorations.dropTargetDecorations)(oldState, newState, api);
38
+ decorations = decorations.add(newState.doc, decs);
39
+ }
40
+ // Remove target decorations when dragging is stopped
41
+ if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false) {
42
+ decorations = _view.DecorationSet.create(newState.doc, []);
43
+ }
22
44
  return {
23
- decorations: decorations
45
+ decorations: decorations,
46
+ activeNode: {
47
+ pos: meta === null || meta === void 0 ? void 0 : meta.pos,
48
+ size: meta === null || meta === void 0 ? void 0 : meta.size
49
+ },
50
+ isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : false,
51
+ isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen
24
52
  };
25
53
  }
26
54
  },
@@ -28,6 +56,40 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
28
56
  decorations: function decorations(state) {
29
57
  var _key$getState;
30
58
  return (_key$getState = key.getState(state)) === null || _key$getState === void 0 ? void 0 : _key$getState.decorations;
59
+ },
60
+ handleDOMEvents: {
61
+ mousemove: function mousemove(view, event) {
62
+ var pos = view.posAtCoords({
63
+ left: event.clientX,
64
+ top: event.clientY
65
+ });
66
+ if (pos !== null && pos !== void 0 && pos.inside && pos.inside > 0) {
67
+ var _api$core;
68
+ var node = view.state.doc.nodeAt(pos.inside);
69
+ if (!node) {
70
+ return;
71
+ }
72
+ var resolvedPos = view.state.doc.resolve(pos.pos);
73
+ var topLevelPos = resolvedPos.before(1); // 1 here restricts the depth to the root level
74
+ var topLevelNode = view.state.doc.nodeAt(topLevelPos);
75
+ if (!topLevelNode) {
76
+ return;
77
+ }
78
+ var dom = view.nodeDOM(topLevelPos);
79
+ if (!dom) {
80
+ return;
81
+ }
82
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref) {
83
+ var tr = _ref.tr;
84
+ return tr.setMeta(key, {
85
+ pos: topLevelPos,
86
+ size: topLevelNode.nodeSize,
87
+ dom: dom,
88
+ type: topLevelNode.type.name
89
+ });
90
+ });
91
+ }
92
+ }
31
93
  }
32
94
  }
33
95
  });
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DRAG_HANDLE_WIDTH = exports.DRAG_HANDLE_HEIGHT = void 0;
7
+ var DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_HEIGHT = 48;
8
+ var DRAG_HANDLE_WIDTH = exports.DRAG_HANDLE_WIDTH = 24;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.DragHandleMenu = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _hooks = require("@atlaskit/editor-common/hooks");
10
+ var DragHandleMenu = exports.DragHandleMenu = function DragHandleMenu(_ref) {
11
+ var api = _ref.api;
12
+ var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['blockControls']),
13
+ blockControlsState = _useSharedPluginState.blockControlsState;
14
+ return blockControlsState !== null && blockControlsState !== void 0 && blockControlsState.isMenuOpen ? /*#__PURE__*/_react.default.createElement("div", null, "menu") : null;
15
+ };
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DragHandle = void 0;
7
+ var _react = require("react");
8
+ var _react2 = require("@emotion/react");
9
+ var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
10
+ var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
11
+ var _setCustomNativeDragPreview = require("@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview");
12
+ var _main = require("../pm-plugins/main");
13
+ var _consts = require("./consts");
14
+ var _dragPreview = require("./drag-preview");
15
+ /** @jsx jsx */
16
+
17
+ var styles = (0, _react2.css)({
18
+ position: 'absolute',
19
+ zIndex: 1,
20
+ height: _consts.DRAG_HANDLE_HEIGHT,
21
+ width: _consts.DRAG_HANDLE_WIDTH,
22
+ left: -_consts.DRAG_HANDLE_WIDTH
23
+ });
24
+ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
25
+ var dom = _ref.dom,
26
+ api = _ref.api,
27
+ start = _ref.start,
28
+ end = _ref.end;
29
+ var buttonRef = (0, _react.useRef)(null);
30
+ var domRef = (0, _react.useRef)(dom);
31
+ (0, _react.useEffect)(function () {
32
+ var element = buttonRef.current;
33
+ if (!element) {
34
+ return;
35
+ }
36
+ return (0, _combine.combine)((0, _adapter.draggable)({
37
+ element: element,
38
+ getInitialData: function getInitialData() {
39
+ return {
40
+ start: start,
41
+ end: end
42
+ };
43
+ },
44
+ onGenerateDragPreview: function onGenerateDragPreview(_ref2) {
45
+ var nativeSetDragImage = _ref2.nativeSetDragImage;
46
+ (0, _setCustomNativeDragPreview.setCustomNativeDragPreview)({
47
+ getOffset: function getOffset() {
48
+ var rect = domRef.current.getBoundingClientRect();
49
+ // Offset the drag preview to the center of the element
50
+ return {
51
+ x: 0,
52
+ y: rect.height / 2
53
+ };
54
+ },
55
+ render: function render(_ref3) {
56
+ var container = _ref3.container;
57
+ return (0, _dragPreview.dragPreview)(container, domRef);
58
+ },
59
+ nativeSetDragImage: nativeSetDragImage
60
+ });
61
+ },
62
+ onDragStart: function onDragStart() {
63
+ var _api$core;
64
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref4) {
65
+ var tr = _ref4.tr;
66
+ return tr.setMeta(_main.key, {
67
+ isDragging: true
68
+ });
69
+ });
70
+ },
71
+ onDrop: function onDrop() {
72
+ var _api$core2;
73
+ api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref5) {
74
+ var tr = _ref5.tr;
75
+ return tr.setMeta(_main.key, {
76
+ isDragging: false
77
+ });
78
+ });
79
+ }
80
+ }));
81
+ }, [api, start, end]);
82
+ return (0, _react2.jsx)("button", {
83
+ css: styles,
84
+ style: {
85
+ bottom: dom.clientHeight / 2 - _consts.DRAG_HANDLE_HEIGHT / 2
86
+ },
87
+ ref: buttonRef,
88
+ type: "button",
89
+ onClick: function onClick() {
90
+ var _api$core3;
91
+ api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref6) {
92
+ var tr = _ref6.tr;
93
+ return tr.setMeta(_main.key, {
94
+ toggleMenu: true
95
+ });
96
+ });
97
+ }
98
+ });
99
+ };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.dragPreview = void 0;
7
+ var dragPreview = exports.dragPreview = function dragPreview(container, domRef) {
8
+ var rect = domRef.current.getBoundingClientRect();
9
+ container.style.width = "".concat(rect.width, "px");
10
+ container.style.height = "".concat(rect.height, "px");
11
+ container.style.pointerEvents = 'none';
12
+ var parent = document.createElement('div');
13
+ // ProseMirror class is required to make sure the cloned dom is styled correctly
14
+ parent.classList.add('ProseMirror');
15
+ var clonedDom = domRef.current.cloneNode(true);
16
+
17
+ // Remove any margin from the cloned element to ensure is doesn't position incorrectly
18
+ clonedDom.style.marginLeft = '0';
19
+ clonedDom.style.marginTop = '0';
20
+ clonedDom.style.marginRight = '0';
21
+ clonedDom.style.marginBottom = '0';
22
+ parent.appendChild(clonedDom);
23
+ container.appendChild(parent);
24
+ var scrollParent = document.querySelector('.fabric-editor-popup-scroll-parent');
25
+ var scrollParentClassNames = scrollParent === null || scrollParent === void 0 ? void 0 : scrollParent.className;
26
+
27
+ // Add the scroll parent class to the container to ensure the cloned element is styled correctly
28
+ container.className = scrollParentClassNames || '';
29
+ container.classList.remove('fabric-editor-popup-scroll-parent');
30
+ // Prevents a scrollbar from showing
31
+ container.style.overflow = 'visible';
32
+ return function () {
33
+ return container;
34
+ };
35
+ };
@@ -0,0 +1,57 @@
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.DropTarget = void 0;
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _react = _interopRequireWildcard(require("react"));
11
+ var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
12
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
13
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
14
+ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
15
+ var api = _ref.api,
16
+ pos = _ref.pos;
17
+ var ref = (0, _react.useRef)(null);
18
+ var _useState = (0, _react.useState)(false),
19
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
20
+ isDraggedOver = _useState2[0],
21
+ setIsDraggedOver = _useState2[1];
22
+ (0, _react.useEffect)(function () {
23
+ var element = ref.current;
24
+ if (!element) {
25
+ return;
26
+ }
27
+ return (0, _adapter.dropTargetForElements)({
28
+ element: element,
29
+ getIsSticky: function getIsSticky() {
30
+ return true;
31
+ },
32
+ onDragEnter: function onDragEnter() {
33
+ return setIsDraggedOver(true);
34
+ },
35
+ onDragLeave: function onDragLeave() {
36
+ return setIsDraggedOver(false);
37
+ },
38
+ onDrop: function onDrop(event) {
39
+ var _api$core, _api$blockControls;
40
+ var _ref2 = event.source.data,
41
+ start = _ref2.start,
42
+ end = _ref2.end;
43
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.moveNode(start, end, pos));
44
+ }
45
+ });
46
+ }, [pos, api]);
47
+ return /*#__PURE__*/_react.default.createElement("div", {
48
+ style: {
49
+ height: '20px',
50
+ marginTop: '-22px',
51
+ top: '10px',
52
+ position: 'relative',
53
+ borderBottom: "solid ".concat(isDraggedOver ? 'blue' : 'transparent', " 2px")
54
+ },
55
+ ref: ref
56
+ });
57
+ };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.GlobalStylesWrapper = void 0;
7
+ var _react = require("@emotion/react");
8
+ /** @jsx jsx */
9
+
10
+ var globalStyles = (0, _react.css)({
11
+ '.ProseMirror-widget:first-child + *': {
12
+ 'margin-top': '0 !important'
13
+ }
14
+ });
15
+ var GlobalStylesWrapper = exports.GlobalStylesWrapper = function GlobalStylesWrapper() {
16
+ return (0, _react.jsx)(_react.Global, {
17
+ styles: globalStyles
18
+ });
19
+ };
@@ -1,4 +1,7 @@
1
- import { createPlugin } from './pm-plugins/main';
1
+ import React from 'react';
2
+ import { createPlugin, key } from './pm-plugins/main';
3
+ import { DragHandleMenu } from './ui/drag-handle-menu';
4
+ import { GlobalStylesWrapper } from './ui/global-styles';
2
5
  export const blockControlsPlugin = ({
3
6
  api
4
7
  }) => ({
@@ -9,7 +12,30 @@ export const blockControlsPlugin = ({
9
12
  plugin: () => createPlugin(api)
10
13
  }];
11
14
  },
12
- getSharedState(_editorState) {
13
- return undefined;
15
+ commands: {
16
+ moveNode: (start, end, to) => ({
17
+ tr
18
+ }) => {
19
+ var _api$core;
20
+ let node = tr.doc.content.cut(start, end); // cut the content
21
+ tr.delete(start, end); // delete the content from the original position
22
+ tr.insert(tr.mapping.map(to), node); // insert the content at the new position
23
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.focus();
24
+ return tr;
25
+ }
26
+ },
27
+ getSharedState(editorState) {
28
+ var _key$getState$isMenuO, _key$getState;
29
+ if (!editorState) {
30
+ return undefined;
31
+ }
32
+ return {
33
+ isMenuOpen: (_key$getState$isMenuO = (_key$getState = key.getState(editorState)) === null || _key$getState === void 0 ? void 0 : _key$getState.isMenuOpen) !== null && _key$getState$isMenuO !== void 0 ? _key$getState$isMenuO : false
34
+ };
35
+ },
36
+ contentComponent() {
37
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DragHandleMenu, {
38
+ api: api
39
+ }), /*#__PURE__*/React.createElement(GlobalStylesWrapper, null));
14
40
  }
15
41
  });
@@ -0,0 +1,43 @@
1
+ import { createElement } from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
+ import { DragHandle } from '../ui/drag-handle';
5
+ import { DropTarget } from '../ui/drop-target';
6
+ export const dropTargetDecorations = (oldState, newState, api) => {
7
+ const decorations = [];
8
+ oldState.doc.nodesBetween(0, newState.doc.nodeSize - 2, (node, pos) => {
9
+ decorations.push(Decoration.widget(pos + node.nodeSize, () => {
10
+ const element = document.createElement('div');
11
+ ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
12
+ api,
13
+ pos: pos + node.nodeSize
14
+ }), element);
15
+ return element;
16
+ }));
17
+ return false;
18
+ });
19
+ decorations.push(Decoration.widget(0, () => {
20
+ const element = document.createElement('div');
21
+ ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
22
+ api,
23
+ pos: 0
24
+ }), element);
25
+ return element;
26
+ }));
27
+ return decorations;
28
+ };
29
+ export const dragHandleDecoration = (oldState,
30
+ // @ts-ignore
31
+ meta, api) => {
32
+ return DecorationSet.create(oldState.doc, [Decoration.widget(meta.pos + meta.size, (view, getPos) => {
33
+ const element = document.createElement('div');
34
+ ReactDOM.render( /*#__PURE__*/createElement(DragHandle, {
35
+ dom: meta.dom,
36
+ api,
37
+ start: meta.pos,
38
+ end: meta.pos + meta.size
39
+ }), element);
40
+ element.style.position = 'absolute';
41
+ return element;
42
+ })]);
43
+ };
@@ -1,6 +1,7 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
+ import { dragHandleDecoration, dropTargetDecorations } from './decorations';
4
5
  export const key = new PluginKey('blockControls');
5
6
  export const createPlugin = api => {
6
7
  return new SafePlugin({
@@ -8,15 +9,42 @@ export const createPlugin = api => {
8
9
  state: {
9
10
  init() {
10
11
  return {
11
- decorations: DecorationSet.empty
12
+ decorations: DecorationSet.empty,
13
+ activeNode: null,
14
+ isDragging: false,
15
+ isMenuOpen: false
12
16
  };
13
17
  },
14
- apply(tr, currentState) {
15
- const {
16
- decorations
18
+ apply(tr, currentState, oldState, newState) {
19
+ var _meta$isDragging;
20
+ let {
21
+ activeNode,
22
+ decorations,
23
+ isMenuOpen
17
24
  } = currentState;
25
+ const meta = tr.getMeta(key);
26
+ // Drag handle decoration
27
+ if (meta && meta.pos !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos) && api) {
28
+ decorations = dragHandleDecoration(newState, meta, api);
29
+ }
30
+ // Drop target decorations
31
+ if (meta !== null && meta !== void 0 && meta.isDragging && api) {
32
+ decorations = DecorationSet.create(newState.doc, []);
33
+ const decs = dropTargetDecorations(oldState, newState, api);
34
+ decorations = decorations.add(newState.doc, decs);
35
+ }
36
+ // Remove target decorations when dragging is stopped
37
+ if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false) {
38
+ decorations = DecorationSet.create(newState.doc, []);
39
+ }
18
40
  return {
19
- decorations
41
+ decorations,
42
+ activeNode: {
43
+ pos: meta === null || meta === void 0 ? void 0 : meta.pos,
44
+ size: meta === null || meta === void 0 ? void 0 : meta.size
45
+ },
46
+ isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : false,
47
+ isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen
20
48
  };
21
49
  }
22
50
  },
@@ -24,6 +52,39 @@ export const createPlugin = api => {
24
52
  decorations: state => {
25
53
  var _key$getState;
26
54
  return (_key$getState = key.getState(state)) === null || _key$getState === void 0 ? void 0 : _key$getState.decorations;
55
+ },
56
+ handleDOMEvents: {
57
+ mousemove(view, event) {
58
+ const pos = view.posAtCoords({
59
+ left: event.clientX,
60
+ top: event.clientY
61
+ });
62
+ if (pos !== null && pos !== void 0 && pos.inside && pos.inside > 0) {
63
+ var _api$core;
64
+ const node = view.state.doc.nodeAt(pos.inside);
65
+ if (!node) {
66
+ return;
67
+ }
68
+ const resolvedPos = view.state.doc.resolve(pos.pos);
69
+ const topLevelPos = resolvedPos.before(1); // 1 here restricts the depth to the root level
70
+ const topLevelNode = view.state.doc.nodeAt(topLevelPos);
71
+ if (!topLevelNode) {
72
+ return;
73
+ }
74
+ const dom = view.nodeDOM(topLevelPos);
75
+ if (!dom) {
76
+ return;
77
+ }
78
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
79
+ tr
80
+ }) => tr.setMeta(key, {
81
+ pos: topLevelPos,
82
+ size: topLevelNode.nodeSize,
83
+ dom,
84
+ type: topLevelNode.type.name
85
+ }));
86
+ }
87
+ }
27
88
  }
28
89
  }
29
90
  });
@@ -0,0 +1,2 @@
1
+ export const DRAG_HANDLE_HEIGHT = 48;
2
+ export const DRAG_HANDLE_WIDTH = 24;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
3
+ export const DragHandleMenu = ({
4
+ api
5
+ }) => {
6
+ const {
7
+ blockControlsState
8
+ } = useSharedPluginState(api, ['blockControls']);
9
+ return blockControlsState !== null && blockControlsState !== void 0 && blockControlsState.isMenuOpen ? /*#__PURE__*/React.createElement("div", null, "menu") : null;
10
+ };