@atlaskit/editor-plugin-block-controls 1.4.15 → 1.4.17

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,23 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 1.4.17
4
+
5
+ ### Patch Changes
6
+
7
+ - [#110808](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/110808)
8
+ [`3ae32439b454c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/3ae32439b454c) -
9
+ ED-23725 Fix issue where drag and drop breaks after node type changes and when text selection is
10
+ not allowed if user moves mouse to node before page finishes loading
11
+
12
+ ## 1.4.16
13
+
14
+ ### Patch Changes
15
+
16
+ - [#108805](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/108805)
17
+ [`3695cb26b9899`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/3695cb26b9899) -
18
+ Add analytic events for drag events
19
+ - Updated dependencies
20
+
3
21
  ## 1.4.15
4
22
 
5
23
  ### Patch Changes
@@ -7,11 +7,48 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.key = exports.createPlugin = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _rafSchd = _interopRequireDefault(require("raf-schd"));
10
+ var _analytics = require("@atlaskit/editor-common/analytics");
10
11
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
11
12
  var _state = require("@atlaskit/editor-prosemirror/state");
12
13
  var _view = require("@atlaskit/editor-prosemirror/view");
14
+ var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
13
15
  var _decorations = require("./decorations");
14
16
  var key = exports.key = new _state.PluginKey('blockControls');
17
+ var destroyFn = function destroyFn(api) {
18
+ return (0, _adapter.monitorForElements)({
19
+ canMonitor: function canMonitor(_ref) {
20
+ var source = _ref.source;
21
+ return source.data.type === 'element';
22
+ },
23
+ onDrop: function onDrop(_ref2) {
24
+ var location = _ref2.location,
25
+ source = _ref2.source;
26
+ // if no drop targets are rendered, assume that drop is invalid
27
+ if (location.current.dropTargets.length === 0) {
28
+ var _api$core;
29
+ var _ref3 = source.data,
30
+ start = _ref3.start;
31
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref4) {
32
+ var _api$analytics;
33
+ var tr = _ref4.tr;
34
+ var resolvedMovingNode = tr.doc.resolve(start);
35
+ var maybeNode = resolvedMovingNode.nodeAfter;
36
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
37
+ eventType: _analytics.EVENT_TYPE.UI,
38
+ action: _analytics.ACTION.CANCELLED,
39
+ actionSubject: _analytics.ACTION_SUBJECT.DRAG,
40
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
41
+ attributes: {
42
+ nodeDepth: resolvedMovingNode.depth,
43
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
44
+ }
45
+ })(tr);
46
+ return tr;
47
+ });
48
+ }
49
+ }
50
+ });
51
+ };
15
52
  var createPlugin = exports.createPlugin = function createPlugin(api) {
16
53
  return new _safePlugin.SafePlugin({
17
54
  key: key,
@@ -52,8 +89,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
52
89
 
53
90
  // Remove previous drag handle widget and draw new drag handle widget when activeNode changes
54
91
  if (meta !== null && meta !== void 0 && meta.activeNode && (meta === null || meta === void 0 ? void 0 : meta.activeNode.pos) !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos) && (meta === null || meta === void 0 ? void 0 : meta.activeNode.anchorName) !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName) && api) {
55
- var oldHandle = decorations.find().filter(function (_ref) {
56
- var spec = _ref.spec;
92
+ var oldHandle = decorations.find().filter(function (_ref5) {
93
+ var spec = _ref5.spec;
57
94
  return spec.id === 'drag-handle';
58
95
  });
59
96
  decorations = decorations.remove(oldHandle);
@@ -72,8 +109,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
72
109
 
73
110
  // Remove drop target decoration when dragging stops
74
111
  if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false && !tr.docChanged) {
75
- var dropTargetDecs = decorations.find().filter(function (_ref2) {
76
- var spec = _ref2.spec;
112
+ var dropTargetDecs = decorations.find().filter(function (_ref6) {
113
+ var spec = _ref6.spec;
77
114
  return spec.type === 'drop-target-decoration';
78
115
  });
79
116
  decorations = decorations.remove(dropTargetDecs);
@@ -81,9 +118,9 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
81
118
 
82
119
  // Map drop target decoration positions when the document changes
83
120
  if (tr.docChanged && currentState.isDragging) {
84
- decorationState = decorationState.map(function (_ref3) {
85
- var index = _ref3.index,
86
- pos = _ref3.pos;
121
+ decorationState = decorationState.map(function (_ref7) {
122
+ var index = _ref7.index,
123
+ pos = _ref7.pos;
87
124
  return {
88
125
  index: index,
89
126
  pos: tr.mapping.map(pos)
@@ -143,6 +180,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
143
180
  return {
144
181
  destroy: function destroy() {
145
182
  resizeObserver.unobserve(dom);
183
+ return destroyFn(api);
146
184
  }
147
185
  };
148
186
  }
@@ -105,6 +105,12 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
105
105
  }
106
106
  return (0, _adapter.draggable)({
107
107
  element: element,
108
+ getInitialData: function getInitialData() {
109
+ return {
110
+ type: 'element',
111
+ start: start
112
+ };
113
+ },
108
114
  onGenerateDragPreview: function onGenerateDragPreview(_ref4) {
109
115
  var nativeSetDragImage = _ref4.nativeSetDragImage;
110
116
  (0, _setCustomNativeDragPreview.setCustomNativeDragPreview)({
@@ -8,6 +8,7 @@ exports.DropTarget = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
9
  var _react = require("react");
10
10
  var _react2 = require("@emotion/react");
11
+ var _analytics = require("@atlaskit/editor-common/analytics");
11
12
  var _hooks = require("@atlaskit/editor-common/hooks");
12
13
  var _element = require("@atlaskit/pragmatic-drag-and-drop-auto-scroll/element");
13
14
  var _box = require("@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box");
@@ -62,7 +63,7 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
62
63
  scrollable.style.setProperty('scroll-behavior', 'unset');
63
64
  },
64
65
  onDragEnter: function onDragEnter() {
65
- return setIsDraggedOver(true);
66
+ setIsDraggedOver(true);
66
67
  },
67
68
  onDragLeave: function onDragLeave() {
68
69
  return setIsDraggedOver(false);
@@ -81,9 +82,25 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
81
82
  }) || {},
82
83
  pos = _ref3.pos;
83
84
  if (activeNode && pos !== undefined) {
84
- var _api$core, _api$blockControls2;
85
+ var _api$core;
85
86
  var start = activeNode.pos;
86
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.moveNode(start, pos));
87
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (state) {
88
+ var _api$blockControls2, _api$analytics;
89
+ var resolvedMovingNode = state.tr.doc.resolve(start);
90
+ var maybeNode = resolvedMovingNode.nodeAfter;
91
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 || _api$blockControls2.moveNode(start, pos)(state);
92
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
93
+ eventType: _analytics.EVENT_TYPE.UI,
94
+ action: _analytics.ACTION.DRAGGED,
95
+ actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
96
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
97
+ attributes: {
98
+ nodeDepth: resolvedMovingNode.depth,
99
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
100
+ }
101
+ })(state.tr);
102
+ return state.tr;
103
+ });
87
104
  }
88
105
  }
89
106
  }));
@@ -96,7 +113,7 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
96
113
  ref: ref,
97
114
  "data-testid": "block-ctrl-drop-target"
98
115
  },
99
- //4px gap to clear expand node border
116
+ // 4px gap to clear expand node border
100
117
  isDraggedOver && (0, _react2.jsx)("div", {
101
118
  css: styleDropIndicator,
102
119
  style: {
@@ -8,6 +8,7 @@ exports.MouseMoveWrapper = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
9
  var _react = require("react");
10
10
  var _react2 = require("@emotion/react");
11
+ var _hooks = require("@atlaskit/editor-common/hooks");
11
12
  var _dragHandlePositions = require("../utils/drag-handle-positions");
12
13
  /** @jsx jsx */
13
14
 
@@ -22,16 +23,22 @@ var mouseMoveWrapperStyles = (0, _react2.css)({
22
23
  zIndex: 1
23
24
  });
24
25
  var MouseMoveWrapper = exports.MouseMoveWrapper = function MouseMoveWrapper(_ref) {
26
+ var _blockControlsState$a;
25
27
  var view = _ref.view,
26
28
  api = _ref.api,
27
29
  anchorName = _ref.anchorName,
28
30
  nodeType = _ref.nodeType,
29
31
  getPos = _ref.getPos;
32
+ var nodePos = (0, _react.useMemo)(function () {
33
+ return getPos();
34
+ }, [getPos]);
35
+ var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['blockControls']),
36
+ blockControlsState = _useSharedPluginState.blockControlsState;
30
37
  var _useState = (0, _react.useState)(false),
31
38
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
32
39
  isDragging = _useState2[0],
33
40
  setIsDragging = _useState2[1];
34
- var _useState3 = (0, _react.useState)(false),
41
+ var _useState3 = (0, _react.useState)((blockControlsState === null || blockControlsState === void 0 || (_blockControlsState$a = blockControlsState.activeNode) === null || _blockControlsState$a === void 0 ? void 0 : _blockControlsState$a.pos) === nodePos),
35
42
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
36
43
  hideWrapper = _useState4[0],
37
44
  setHideWrapper = _useState4[1];
@@ -43,38 +50,36 @@ var MouseMoveWrapper = exports.MouseMoveWrapper = function MouseMoveWrapper(_ref
43
50
  if (!isDragging) {
44
51
  setHideWrapper(true);
45
52
  }
46
- var pos = getPos();
47
- if (pos === undefined) {
53
+ if (nodePos === undefined) {
48
54
  return;
49
55
  }
50
56
  if (api && api.blockControls && !isDragging) {
51
57
  var _api$core;
52
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(pos, anchorName, nodeType));
58
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(nodePos, anchorName, nodeType));
53
59
  }
54
- }, [setHideWrapper, isDragging, api, getPos, anchorName, nodeType]);
60
+ }, [setHideWrapper, isDragging, api, nodePos, anchorName, nodeType]);
55
61
  (0, _react.useEffect)(function () {
56
62
  var _api$blockControls;
57
63
  var unbind = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(function (_ref2) {
58
64
  var _nextSharedState$acti;
59
65
  var nextSharedState = _ref2.nextSharedState;
60
- var pos = getPos();
61
66
  setIsDragging(Boolean(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging));
62
67
  if (!(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.activeNode)) {
63
68
  return;
64
69
  }
65
- if ((nextSharedState === null || nextSharedState === void 0 || (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.pos) !== pos && !(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging)) {
70
+ if ((nextSharedState === null || nextSharedState === void 0 || (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.pos) !== nodePos && !(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging)) {
66
71
  setHideWrapper(false);
67
72
  return;
68
73
  }
69
74
  if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging) {
70
- setHideWrapper(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging);
75
+ setHideWrapper(true);
71
76
  return;
72
77
  }
73
78
  });
74
79
  return function () {
75
80
  unbind === null || unbind === void 0 || unbind();
76
81
  };
77
- }, [getPos, api]);
82
+ }, [nodePos, api]);
78
83
  (0, _react.useLayoutEffect)(function () {
79
84
  var supportsAnchor = CSS.supports('height', "anchor-size(".concat(anchorName, " height)")) && CSS.supports('top', "anchor(".concat(anchorName, " start)"));
80
85
  if (supportsAnchor) {
@@ -1,9 +1,48 @@
1
1
  import rafSchedule from 'raf-schd';
2
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
3
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
4
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
5
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
5
7
  import { dragHandleDecoration, dropTargetDecorations, mouseMoveWrapperDecorations, nodeDecorations } from './decorations';
6
8
  export const key = new PluginKey('blockControls');
9
+ const destroyFn = api => {
10
+ return monitorForElements({
11
+ canMonitor: ({
12
+ source
13
+ }) => source.data.type === 'element',
14
+ onDrop: ({
15
+ location,
16
+ source
17
+ }) => {
18
+ // if no drop targets are rendered, assume that drop is invalid
19
+ if (location.current.dropTargets.length === 0) {
20
+ var _api$core;
21
+ const {
22
+ start
23
+ } = source.data;
24
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
25
+ tr
26
+ }) => {
27
+ var _api$analytics;
28
+ const resolvedMovingNode = tr.doc.resolve(start);
29
+ const maybeNode = resolvedMovingNode.nodeAfter;
30
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
31
+ eventType: EVENT_TYPE.UI,
32
+ action: ACTION.CANCELLED,
33
+ actionSubject: ACTION_SUBJECT.DRAG,
34
+ actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
35
+ attributes: {
36
+ nodeDepth: resolvedMovingNode.depth,
37
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
38
+ }
39
+ })(tr);
40
+ return tr;
41
+ });
42
+ }
43
+ }
44
+ });
45
+ };
7
46
  export const createPlugin = api => {
8
47
  return new SafePlugin({
9
48
  key,
@@ -137,6 +176,7 @@ export const createPlugin = api => {
137
176
  return {
138
177
  destroy() {
139
178
  resizeObserver.unobserve(dom);
179
+ return destroyFn(api);
140
180
  }
141
181
  };
142
182
  }
@@ -97,6 +97,10 @@ export const DragHandle = ({
97
97
  }
98
98
  return draggable({
99
99
  element,
100
+ getInitialData: () => ({
101
+ type: 'element',
102
+ start
103
+ }),
100
104
  onGenerateDragPreview: ({
101
105
  nativeSetDragImage
102
106
  }) => {
@@ -1,6 +1,7 @@
1
1
  /** @jsx jsx */
2
2
  import { useEffect, useRef, useState } from 'react';
3
3
  import { css, jsx } from '@emotion/react';
4
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
4
5
  import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
5
6
  import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
6
7
  import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
@@ -49,7 +50,9 @@ export const DropTarget = ({
49
50
  onDrag: () => {
50
51
  scrollable.style.setProperty('scroll-behavior', 'unset');
51
52
  },
52
- onDragEnter: () => setIsDraggedOver(true),
53
+ onDragEnter: () => {
54
+ setIsDraggedOver(true);
55
+ },
53
56
  onDragLeave: () => setIsDraggedOver(false),
54
57
  onDrop: () => {
55
58
  var _api$blockControls;
@@ -65,11 +68,27 @@ export const DropTarget = ({
65
68
  pos
66
69
  } = decorationState.find(dec => dec.index === index) || {};
67
70
  if (activeNode && pos !== undefined) {
68
- var _api$core, _api$blockControls2, _api$blockControls2$c;
71
+ var _api$core;
69
72
  const {
70
73
  pos: start
71
74
  } = activeNode;
72
- api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : (_api$blockControls2$c = _api$blockControls2.commands) === null || _api$blockControls2$c === void 0 ? void 0 : _api$blockControls2$c.moveNode(start, pos));
75
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(state => {
76
+ var _api$blockControls2, _api$blockControls2$c, _api$analytics;
77
+ const resolvedMovingNode = state.tr.doc.resolve(start);
78
+ const maybeNode = resolvedMovingNode.nodeAfter;
79
+ api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : (_api$blockControls2$c = _api$blockControls2.commands) === null || _api$blockControls2$c === void 0 ? void 0 : _api$blockControls2$c.moveNode(start, pos)(state);
80
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
81
+ eventType: EVENT_TYPE.UI,
82
+ action: ACTION.DRAGGED,
83
+ actionSubject: ACTION_SUBJECT.ELEMENT,
84
+ actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
85
+ attributes: {
86
+ nodeDepth: resolvedMovingNode.depth,
87
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
88
+ }
89
+ })(state.tr);
90
+ return state.tr;
91
+ });
73
92
  }
74
93
  }
75
94
  }));
@@ -82,7 +101,7 @@ export const DropTarget = ({
82
101
  ref: ref,
83
102
  "data-testid": "block-ctrl-drop-target"
84
103
  },
85
- //4px gap to clear expand node border
104
+ // 4px gap to clear expand node border
86
105
  isDraggedOver && jsx("div", {
87
106
  css: styleDropIndicator,
88
107
  style: {
@@ -1,6 +1,7 @@
1
1
  /** @jsx jsx */
2
- import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
2
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
3
3
  import { css, jsx } from '@emotion/react';
4
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
4
5
  import { getTopPosition } from '../utils/drag-handle-positions';
5
6
  const basicStyles = css({
6
7
  position: 'absolute',
@@ -19,46 +20,49 @@ export const MouseMoveWrapper = ({
19
20
  nodeType,
20
21
  getPos
21
22
  }) => {
23
+ var _blockControlsState$a;
24
+ const nodePos = useMemo(() => getPos(), [getPos]);
25
+ const {
26
+ blockControlsState
27
+ } = useSharedPluginState(api, ['blockControls']);
22
28
  const [isDragging, setIsDragging] = useState(false);
23
- const [hideWrapper, setHideWrapper] = useState(false);
29
+ const [hideWrapper, setHideWrapper] = useState((blockControlsState === null || blockControlsState === void 0 ? void 0 : (_blockControlsState$a = blockControlsState.activeNode) === null || _blockControlsState$a === void 0 ? void 0 : _blockControlsState$a.pos) === nodePos);
24
30
  const [pos, setPos] = useState();
25
31
  const onMouseEnter = useCallback(() => {
26
32
  if (!isDragging) {
27
33
  setHideWrapper(true);
28
34
  }
29
- const pos = getPos();
30
- if (pos === undefined) {
35
+ if (nodePos === undefined) {
31
36
  return;
32
37
  }
33
38
  if (api && api.blockControls && !isDragging) {
34
39
  var _api$core;
35
- api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(pos, anchorName, nodeType));
40
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(nodePos, anchorName, nodeType));
36
41
  }
37
- }, [setHideWrapper, isDragging, api, getPos, anchorName, nodeType]);
42
+ }, [setHideWrapper, isDragging, api, nodePos, anchorName, nodeType]);
38
43
  useEffect(() => {
39
44
  var _api$blockControls;
40
45
  const unbind = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(({
41
46
  nextSharedState
42
47
  }) => {
43
48
  var _nextSharedState$acti;
44
- const pos = getPos();
45
49
  setIsDragging(Boolean(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging));
46
50
  if (!(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.activeNode)) {
47
51
  return;
48
52
  }
49
- if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.pos) !== pos && !(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging)) {
53
+ if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.pos) !== nodePos && !(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging)) {
50
54
  setHideWrapper(false);
51
55
  return;
52
56
  }
53
57
  if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging) {
54
- setHideWrapper(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging);
58
+ setHideWrapper(true);
55
59
  return;
56
60
  }
57
61
  });
58
62
  return () => {
59
63
  unbind === null || unbind === void 0 ? void 0 : unbind();
60
64
  };
61
- }, [getPos, api]);
65
+ }, [nodePos, api]);
62
66
  useLayoutEffect(() => {
63
67
  const supportsAnchor = CSS.supports('height', `anchor-size(${anchorName} height)`) && CSS.supports('top', `anchor(${anchorName} start)`);
64
68
  if (supportsAnchor) {
@@ -1,10 +1,47 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import rafSchedule from 'raf-schd';
3
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
5
6
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
6
8
  import { dragHandleDecoration, dropTargetDecorations, mouseMoveWrapperDecorations, nodeDecorations } from './decorations';
7
9
  export var key = new PluginKey('blockControls');
10
+ var destroyFn = function destroyFn(api) {
11
+ return monitorForElements({
12
+ canMonitor: function canMonitor(_ref) {
13
+ var source = _ref.source;
14
+ return source.data.type === 'element';
15
+ },
16
+ onDrop: function onDrop(_ref2) {
17
+ var location = _ref2.location,
18
+ source = _ref2.source;
19
+ // if no drop targets are rendered, assume that drop is invalid
20
+ if (location.current.dropTargets.length === 0) {
21
+ var _api$core;
22
+ var _ref3 = source.data,
23
+ start = _ref3.start;
24
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref4) {
25
+ var _api$analytics;
26
+ var tr = _ref4.tr;
27
+ var resolvedMovingNode = tr.doc.resolve(start);
28
+ var maybeNode = resolvedMovingNode.nodeAfter;
29
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
30
+ eventType: EVENT_TYPE.UI,
31
+ action: ACTION.CANCELLED,
32
+ actionSubject: ACTION_SUBJECT.DRAG,
33
+ actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
34
+ attributes: {
35
+ nodeDepth: resolvedMovingNode.depth,
36
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
37
+ }
38
+ })(tr);
39
+ return tr;
40
+ });
41
+ }
42
+ }
43
+ });
44
+ };
8
45
  export var createPlugin = function createPlugin(api) {
9
46
  return new SafePlugin({
10
47
  key: key,
@@ -45,8 +82,8 @@ export var createPlugin = function createPlugin(api) {
45
82
 
46
83
  // Remove previous drag handle widget and draw new drag handle widget when activeNode changes
47
84
  if (meta !== null && meta !== void 0 && meta.activeNode && (meta === null || meta === void 0 ? void 0 : meta.activeNode.pos) !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos) && (meta === null || meta === void 0 ? void 0 : meta.activeNode.anchorName) !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName) && api) {
48
- var oldHandle = decorations.find().filter(function (_ref) {
49
- var spec = _ref.spec;
85
+ var oldHandle = decorations.find().filter(function (_ref5) {
86
+ var spec = _ref5.spec;
50
87
  return spec.id === 'drag-handle';
51
88
  });
52
89
  decorations = decorations.remove(oldHandle);
@@ -65,8 +102,8 @@ export var createPlugin = function createPlugin(api) {
65
102
 
66
103
  // Remove drop target decoration when dragging stops
67
104
  if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false && !tr.docChanged) {
68
- var dropTargetDecs = decorations.find().filter(function (_ref2) {
69
- var spec = _ref2.spec;
105
+ var dropTargetDecs = decorations.find().filter(function (_ref6) {
106
+ var spec = _ref6.spec;
70
107
  return spec.type === 'drop-target-decoration';
71
108
  });
72
109
  decorations = decorations.remove(dropTargetDecs);
@@ -74,9 +111,9 @@ export var createPlugin = function createPlugin(api) {
74
111
 
75
112
  // Map drop target decoration positions when the document changes
76
113
  if (tr.docChanged && currentState.isDragging) {
77
- decorationState = decorationState.map(function (_ref3) {
78
- var index = _ref3.index,
79
- pos = _ref3.pos;
114
+ decorationState = decorationState.map(function (_ref7) {
115
+ var index = _ref7.index,
116
+ pos = _ref7.pos;
80
117
  return {
81
118
  index: index,
82
119
  pos: tr.mapping.map(pos)
@@ -136,6 +173,7 @@ export var createPlugin = function createPlugin(api) {
136
173
  return {
137
174
  destroy: function destroy() {
138
175
  resizeObserver.unobserve(dom);
176
+ return destroyFn(api);
139
177
  }
140
178
  };
141
179
  }
@@ -97,6 +97,12 @@ export var DragHandle = function DragHandle(_ref) {
97
97
  }
98
98
  return draggable({
99
99
  element: element,
100
+ getInitialData: function getInitialData() {
101
+ return {
102
+ type: 'element',
103
+ start: start
104
+ };
105
+ },
100
106
  onGenerateDragPreview: function onGenerateDragPreview(_ref4) {
101
107
  var nativeSetDragImage = _ref4.nativeSetDragImage;
102
108
  setCustomNativeDragPreview({
@@ -2,6 +2,7 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  /** @jsx jsx */
3
3
  import { useEffect, useRef, useState } from 'react';
4
4
  import { css, jsx } from '@emotion/react';
5
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
5
6
  import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
6
7
  import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
7
8
  import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
@@ -54,7 +55,7 @@ export var DropTarget = function DropTarget(_ref) {
54
55
  scrollable.style.setProperty('scroll-behavior', 'unset');
55
56
  },
56
57
  onDragEnter: function onDragEnter() {
57
- return setIsDraggedOver(true);
58
+ setIsDraggedOver(true);
58
59
  },
59
60
  onDragLeave: function onDragLeave() {
60
61
  return setIsDraggedOver(false);
@@ -73,9 +74,25 @@ export var DropTarget = function DropTarget(_ref) {
73
74
  }) || {},
74
75
  pos = _ref3.pos;
75
76
  if (activeNode && pos !== undefined) {
76
- var _api$core, _api$blockControls2;
77
+ var _api$core;
77
78
  var start = activeNode.pos;
78
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.moveNode(start, pos));
79
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (state) {
80
+ var _api$blockControls2, _api$analytics;
81
+ var resolvedMovingNode = state.tr.doc.resolve(start);
82
+ var maybeNode = resolvedMovingNode.nodeAfter;
83
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 || _api$blockControls2.moveNode(start, pos)(state);
84
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
85
+ eventType: EVENT_TYPE.UI,
86
+ action: ACTION.DRAGGED,
87
+ actionSubject: ACTION_SUBJECT.ELEMENT,
88
+ actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
89
+ attributes: {
90
+ nodeDepth: resolvedMovingNode.depth,
91
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
92
+ }
93
+ })(state.tr);
94
+ return state.tr;
95
+ });
79
96
  }
80
97
  }
81
98
  }));
@@ -88,7 +105,7 @@ export var DropTarget = function DropTarget(_ref) {
88
105
  ref: ref,
89
106
  "data-testid": "block-ctrl-drop-target"
90
107
  },
91
- //4px gap to clear expand node border
108
+ // 4px gap to clear expand node border
92
109
  isDraggedOver && jsx("div", {
93
110
  css: styleDropIndicator,
94
111
  style: {
@@ -1,7 +1,8 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  /** @jsx jsx */
3
- import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
3
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
4
4
  import { css, jsx } from '@emotion/react';
5
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
5
6
  import { getTopPosition } from '../utils/drag-handle-positions';
6
7
  var basicStyles = css({
7
8
  position: 'absolute',
@@ -14,16 +15,22 @@ var mouseMoveWrapperStyles = css({
14
15
  zIndex: 1
15
16
  });
16
17
  export var MouseMoveWrapper = function MouseMoveWrapper(_ref) {
18
+ var _blockControlsState$a;
17
19
  var view = _ref.view,
18
20
  api = _ref.api,
19
21
  anchorName = _ref.anchorName,
20
22
  nodeType = _ref.nodeType,
21
23
  getPos = _ref.getPos;
24
+ var nodePos = useMemo(function () {
25
+ return getPos();
26
+ }, [getPos]);
27
+ var _useSharedPluginState = useSharedPluginState(api, ['blockControls']),
28
+ blockControlsState = _useSharedPluginState.blockControlsState;
22
29
  var _useState = useState(false),
23
30
  _useState2 = _slicedToArray(_useState, 2),
24
31
  isDragging = _useState2[0],
25
32
  setIsDragging = _useState2[1];
26
- var _useState3 = useState(false),
33
+ var _useState3 = useState((blockControlsState === null || blockControlsState === void 0 || (_blockControlsState$a = blockControlsState.activeNode) === null || _blockControlsState$a === void 0 ? void 0 : _blockControlsState$a.pos) === nodePos),
27
34
  _useState4 = _slicedToArray(_useState3, 2),
28
35
  hideWrapper = _useState4[0],
29
36
  setHideWrapper = _useState4[1];
@@ -35,38 +42,36 @@ export var MouseMoveWrapper = function MouseMoveWrapper(_ref) {
35
42
  if (!isDragging) {
36
43
  setHideWrapper(true);
37
44
  }
38
- var pos = getPos();
39
- if (pos === undefined) {
45
+ if (nodePos === undefined) {
40
46
  return;
41
47
  }
42
48
  if (api && api.blockControls && !isDragging) {
43
49
  var _api$core;
44
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(pos, anchorName, nodeType));
50
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(nodePos, anchorName, nodeType));
45
51
  }
46
- }, [setHideWrapper, isDragging, api, getPos, anchorName, nodeType]);
52
+ }, [setHideWrapper, isDragging, api, nodePos, anchorName, nodeType]);
47
53
  useEffect(function () {
48
54
  var _api$blockControls;
49
55
  var unbind = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(function (_ref2) {
50
56
  var _nextSharedState$acti;
51
57
  var nextSharedState = _ref2.nextSharedState;
52
- var pos = getPos();
53
58
  setIsDragging(Boolean(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging));
54
59
  if (!(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.activeNode)) {
55
60
  return;
56
61
  }
57
- if ((nextSharedState === null || nextSharedState === void 0 || (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.pos) !== pos && !(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging)) {
62
+ if ((nextSharedState === null || nextSharedState === void 0 || (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.pos) !== nodePos && !(nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging)) {
58
63
  setHideWrapper(false);
59
64
  return;
60
65
  }
61
66
  if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging) {
62
- setHideWrapper(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging);
67
+ setHideWrapper(true);
63
68
  return;
64
69
  }
65
70
  });
66
71
  return function () {
67
72
  unbind === null || unbind === void 0 || unbind();
68
73
  };
69
- }, [getPos, api]);
74
+ }, [nodePos, api]);
70
75
  useLayoutEffect(function () {
71
76
  var supportsAnchor = CSS.supports('height', "anchor-size(".concat(anchorName, " height)")) && CSS.supports('top', "anchor(".concat(anchorName, " start)"));
72
77
  if (supportsAnchor) {
@@ -1,4 +1,5 @@
1
1
  import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
2
+ import { type AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
2
3
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
3
4
  import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
4
5
  import type { WidthPlugin } from '@atlaskit/editor-plugin-width';
@@ -20,7 +21,8 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
20
21
  dependencies: [
21
22
  OptionalPlugin<EditorDisabledPlugin>,
22
23
  OptionalPlugin<WidthPlugin>,
23
- OptionalPlugin<FeatureFlagsPlugin>
24
+ OptionalPlugin<FeatureFlagsPlugin>,
25
+ OptionalPlugin<AnalyticsPlugin>
24
26
  ];
25
27
  sharedState: {
26
28
  isMenuOpen: boolean;
@@ -1,4 +1,5 @@
1
1
  import type { EditorCommand, NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
2
+ import { type AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
2
3
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
3
4
  import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
4
5
  import type { WidthPlugin } from '@atlaskit/editor-plugin-width';
@@ -20,7 +21,8 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
20
21
  dependencies: [
21
22
  OptionalPlugin<EditorDisabledPlugin>,
22
23
  OptionalPlugin<WidthPlugin>,
23
- OptionalPlugin<FeatureFlagsPlugin>
24
+ OptionalPlugin<FeatureFlagsPlugin>,
25
+ OptionalPlugin<AnalyticsPlugin>
24
26
  ];
25
27
  sharedState: {
26
28
  isMenuOpen: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "1.4.15",
3
+ "version": "1.4.17",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,8 @@
31
31
  ".": "./src/index.ts"
32
32
  },
33
33
  "dependencies": {
34
- "@atlaskit/editor-common": "^82.4.0",
34
+ "@atlaskit/editor-common": "^82.5.0",
35
+ "@atlaskit/editor-plugin-analytics": "^1.2.3",
35
36
  "@atlaskit/editor-plugin-editor-disabled": "^1.1.5",
36
37
  "@atlaskit/editor-plugin-feature-flags": "^1.1.0",
37
38
  "@atlaskit/editor-plugin-width": "^1.1.0",