@atlaskit/editor-plugin-block-controls 2.0.5 → 2.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#142740](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142740)
8
+ [`a9e5ecde7f694`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/a9e5ecde7f694) -
9
+ Remove redundant childnode checks to improve performance
10
+
11
+ ### Patch Changes
12
+
13
+ - [#142433](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142433)
14
+ [`896303d4b4390`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/896303d4b4390) -
15
+ ED-24552 Update document moved event to fire when nested nodes are cut/paste into nodes and add
16
+ nodeDepth attributes
17
+ - [#142806](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142806)
18
+ [`f73667130fb7d`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/f73667130fb7d) -
19
+ [ux] Update drop target margin for nested panels
20
+ - [#142433](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142433)
21
+ [`a4f9e2c346c40`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/a4f9e2c346c40) -
22
+ ED-24925 re-enable tooltip for top level draghandle
23
+ - Updated dependencies
24
+
25
+ ## 2.0.6
26
+
27
+ ### Patch Changes
28
+
29
+ - [#142709](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/142709)
30
+ [`7ca7608c6b4c8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/7ca7608c6b4c8) -
31
+ [ux] ED-24883 Fixed bug which caused empty line prompt button to jump around in Firefox
32
+ - Updated dependencies
33
+
3
34
  ## 2.0.5
4
35
 
5
36
  ### Patch Changes
@@ -169,15 +169,18 @@ var moveNode = exports.moveNode = function moveNode(api) {
169
169
  nodeMoved: true
170
170
  });
171
171
  api === null || api === void 0 || api.core.actions.focus();
172
+ var $mappedTo = tr.doc.resolve(mappedTo);
172
173
  api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
173
174
  eventType: _analytics.EVENT_TYPE.TRACK,
174
175
  action: _analytics.ACTION.MOVED,
175
176
  actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
176
177
  actionSubjectId: _analytics.ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
177
- attributes: _objectSpread({
178
+ attributes: _objectSpread(_objectSpread({
178
179
  nodeDepth: resolvedNode.depth,
179
180
  nodeType: node.type.name
180
- }, (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873') && {
181
+ }, (0, _experiments.editorExperiment)('nested-dnd', true) && {
182
+ destinationNodeDepth: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth
183
+ }), (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873') && {
181
184
  inputMethod: inputMethod
182
185
  })
183
186
  })(tr);
@@ -184,13 +184,23 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
184
184
  element.style.display = 'inline';
185
185
  element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
186
186
  element.setAttribute('data-blocks-drag-handle-container', 'true');
187
+ var isTopLevelNode = true;
187
188
  if ((0, _experiments.editorExperiment)('nested-dnd', true)) {
188
- unbind = (0, _bindEventListener.bind)(element, {
189
- type: 'mouseover',
190
- listener: function listener(e) {
191
- e.stopPropagation();
192
- }
193
- });
189
+ var $pos = view.state.doc.resolve(pos);
190
+ isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
191
+ /*
192
+ * We disable mouseover event to fix flickering issue on hover
193
+ * However, the tooltip for nested drag handle is not long working.
194
+ */
195
+ if (!isTopLevelNode) {
196
+ // This will also hide the tooltip.
197
+ unbind = (0, _bindEventListener.bind)(element, {
198
+ type: 'mouseover',
199
+ listener: function listener(e) {
200
+ e.stopPropagation();
201
+ }
202
+ });
203
+ }
194
204
  }
195
205
  unmountDecorations('data-blocks-drag-handle-container');
196
206
 
@@ -205,7 +215,8 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
205
215
  getPos: getPos,
206
216
  anchorName: anchorName,
207
217
  nodeType: nodeType,
208
- handleOptions: handleOptions
218
+ handleOptions: handleOptions,
219
+ isTopLevelNode: isTopLevelNode
209
220
  })), element);
210
221
  return element;
211
222
  }, {
@@ -7,9 +7,11 @@ 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 _steps = require("@atlaskit/adf-schema/steps");
10
11
  var _analytics = require("@atlaskit/editor-common/analytics");
11
12
  var _browser = require("@atlaskit/editor-common/browser");
12
13
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
14
+ var _utils = require("@atlaskit/editor-common/utils");
13
15
  var _state = require("@atlaskit/editor-prosemirror/state");
14
16
  var _view = require("@atlaskit/editor-prosemirror/view");
15
17
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
@@ -79,13 +81,6 @@ var destroyFn = function destroyFn(api) {
79
81
  }));
80
82
  return _combine.combine.apply(void 0, cleanupFn);
81
83
  };
82
- function getDocChildrenCount(newState) {
83
- var size = 0;
84
- newState.doc.descendants(function (node) {
85
- size += node.childCount;
86
- });
87
- return size;
88
- }
89
84
  var initialState = {
90
85
  decorations: _view.DecorationSet.empty,
91
86
  activeNode: undefined,
@@ -128,11 +123,16 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
128
123
  exposure: true
129
124
  }) || (0, _experiments.editorExperiment)('nested-dnd', true);
130
125
  var activeNodeWithNewNodeType = null;
131
- var newChildCount = tr.docChanged && (0, _experiments.editorExperiment)('nested-dnd', true) ? getDocChildrenCount(newState) : childCount;
126
+ var newChildCount = tr.docChanged && (0, _experiments.editorExperiment)('nested-dnd', true) ? 0 : childCount;
132
127
  // If tables or media are being resized, we want to hide the drag handle
133
128
  var resizerMeta = tr.getMeta('is-resizer-resizing');
134
129
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
135
- var nodeCountChanged = (0, _experiments.editorExperiment)('nested-dnd', true) ? childCount !== newChildCount : oldState.doc.childCount !== newState.doc.childCount;
130
+ var canIgnoreTr = function canIgnoreTr() {
131
+ return !tr.steps.every(function (e) {
132
+ return e instanceof _steps.AnalyticsStep;
133
+ });
134
+ };
135
+ var nodeCountChanged = (0, _experiments.editorExperiment)('nested-dnd', true) ? !(0, _utils.isTextInput)(tr) && tr.docChanged && canIgnoreTr() : oldState.doc.childCount !== newState.doc.childCount;
136
136
  var shouldRemoveHandle = !tr.getMeta('isRemote');
137
137
 
138
138
  // During resize, remove the drag handle widget so its dom positioning doesn't need to be maintained
@@ -162,10 +162,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
162
162
  var newNodeDecs;
163
163
  if ((0, _experiments.editorExperiment)('nested-dnd', true)) {
164
164
  var _meta$isDragging;
165
- // naive solution while we work on performance optimised approach under ED-24503
166
- newNodeDecs = (0, _decorations.nodeDecorations)(newState);
167
- isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && decsLength !== newNodeDecs.length;
168
- isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && nodeCountChanged;
165
+ isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && nodeCountChanged;
166
+ isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && nodeCountChanged && !(meta !== null && meta !== void 0 && meta.nodeMoved);
169
167
  } else {
170
168
  isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && decsLength !== newState.doc.childCount;
171
169
  }
@@ -187,17 +185,16 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
187
185
  // The tr.meta.activeNode is triggered by the showDragHandleAt function during the mouse entry event
188
186
  // (when the table node rerenders)
189
187
  // The activeNode is from the previous rendering cycle, and verify if they share the same anchor.
190
- var maybeTableWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 || (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && (isPerformanceFix || meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName));
188
+ var maybeTableWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 || (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName);
191
189
  var redrawDecorations = decorations === _view.DecorationSet.empty || (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== editorHeight || (meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== editorWidthLeft || (meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== editorWidthRight || maybeWidthUpdated || nodeCountChanged || maybeTableWidthUpdated || resizerMeta === false || isDecsMissing || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
192
190
 
193
191
  // Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
194
192
  if (redrawDecorations && !isResizerResizing && api) {
195
- var _newNodeDecs;
196
193
  var oldNodeDecs = decorations.find(undefined, undefined, function (spec) {
197
194
  return spec.type !== 'drop-target-decoration';
198
195
  });
199
196
  decorations = decorations.remove(oldNodeDecs);
200
- newNodeDecs = (_newNodeDecs = newNodeDecs) !== null && _newNodeDecs !== void 0 ? _newNodeDecs : (0, _decorations.nodeDecorations)(newState);
197
+ newNodeDecs = (0, _decorations.nodeDecorations)(newState);
201
198
  decorations = decorations.add(newState.doc, (0, _toConsumableArray2.default)(newNodeDecs));
202
199
  if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved) && !isDecsMissing) {
203
200
  var mappedPosisiton = tr.mapping.map(activeNode.pos);
@@ -38,7 +38,7 @@ var getNestedNodeLeftPaddingMargin = exports.getNestedNodeLeftPaddingMargin = fu
38
38
  case 'layoutColumn':
39
39
  return '20px';
40
40
  case 'panel':
41
- return '44px';
41
+ return '40px';
42
42
  case 'tableCell':
43
43
  return '8px';
44
44
  case 'tableHeader':
@@ -76,7 +76,9 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
76
76
  anchorName = _ref.anchorName,
77
77
  nodeType = _ref.nodeType,
78
78
  formatMessage = _ref.intl.formatMessage,
79
- handleOptions = _ref.handleOptions;
79
+ handleOptions = _ref.handleOptions,
80
+ _ref$isTopLevelNode = _ref.isTopLevelNode,
81
+ isTopLevelNode = _ref$isTopLevelNode === void 0 ? true : _ref$isTopLevelNode;
80
82
  var start = getPos();
81
83
  var buttonRef = (0, _react.useRef)(null);
82
84
  var _useState = (0, _react.useState)(768),
@@ -359,7 +361,7 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
359
361
  }))
360
362
  );
361
363
  };
362
- return (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873') ? (0, _react2.jsx)(_tooltip.default, {
364
+ return isTopLevelNode && (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873') ? (0, _react2.jsx)(_tooltip.default, {
363
365
  content: (0, _react2.jsx)(_keymaps.TooltipContentWithMultipleShortcuts, {
364
366
  helpDescriptors: helpDescriptors
365
367
  }),
@@ -102,11 +102,14 @@ var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref
102
102
  };
103
103
  var TypeAheadControlWithIntl = (0, _reactIntlNext.injectIntl)(TypeAheadControl);
104
104
  var toDOM = function toDOM(api, getPos, getIntl) {
105
+ var wrapper = document.createElement('span');
106
+ wrapper.contentEditable = 'false';
107
+ wrapper.setAttribute('data-empty-block-experiment', 'true');
108
+ wrapper.setAttribute('class', 'empty-block-experiment');
105
109
  var element = document.createElement('span');
106
110
  element.contentEditable = 'false';
107
- element.setAttribute('style', 'position: relative');
108
- element.setAttribute('class', 'empty-block-experiment');
109
- element.setAttribute('data-empty-block-experiment', 'true');
111
+ element.setAttribute('style', 'position: absolute;');
112
+ wrapper.appendChild(element);
110
113
  _reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_reactIntlNext.RawIntlProvider, {
111
114
  value: getIntl()
112
115
  }, /*#__PURE__*/(0, _react.createElement)(TypeAheadControlWithIntl, {
@@ -118,8 +121,8 @@ var toDOM = function toDOM(api, getPos, getIntl) {
118
121
  // // Cursor height cannot be controlled via CSS and is handled by the browser.
119
122
  // // see Prosemirror forum: https://discuss.prosemirror.net/t/chrome-caret-cursor-larger-than-the-text-with-inlined-items/5946
120
123
  var cursorHack = document.createTextNode(_whitespace.ZERO_WIDTH_SPACE);
121
- element.appendChild(cursorHack);
122
- return element;
124
+ wrapper.appendChild(cursorHack);
125
+ return wrapper;
123
126
  };
124
127
  var createEmptyBlockWidgetDecoration = exports.createEmptyBlockWidgetDecoration = function createEmptyBlockWidgetDecoration(selection, api, getIntl) {
125
128
  if (selection instanceof _state.TextSelection && selection.$cursor) {
@@ -163,6 +163,7 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
163
163
  nodeMoved: true
164
164
  });
165
165
  api === null || api === void 0 ? void 0 : api.core.actions.focus();
166
+ const $mappedTo = tr.doc.resolve(mappedTo);
166
167
  api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
167
168
  eventType: EVENT_TYPE.TRACK,
168
169
  action: ACTION.MOVED,
@@ -171,6 +172,9 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
171
172
  attributes: {
172
173
  nodeDepth: resolvedNode.depth,
173
174
  nodeType: node.type.name,
175
+ ...(editorExperiment('nested-dnd', true) && {
176
+ destinationNodeDepth: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth
177
+ }),
174
178
  ...(fg('platform_editor_element_drag_and_drop_ed_23873') && {
175
179
  inputMethod
176
180
  })
@@ -165,13 +165,23 @@ export const dragHandleDecoration = (api, getIntl, pos, anchorName, nodeType, ha
165
165
  element.style.display = 'inline';
166
166
  element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
167
167
  element.setAttribute('data-blocks-drag-handle-container', 'true');
168
+ let isTopLevelNode = true;
168
169
  if (editorExperiment('nested-dnd', true)) {
169
- unbind = bind(element, {
170
- type: 'mouseover',
171
- listener: e => {
172
- e.stopPropagation();
173
- }
174
- });
170
+ const $pos = view.state.doc.resolve(pos);
171
+ isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
172
+ /*
173
+ * We disable mouseover event to fix flickering issue on hover
174
+ * However, the tooltip for nested drag handle is not long working.
175
+ */
176
+ if (!isTopLevelNode) {
177
+ // This will also hide the tooltip.
178
+ unbind = bind(element, {
179
+ type: 'mouseover',
180
+ listener: e => {
181
+ e.stopPropagation();
182
+ }
183
+ });
184
+ }
175
185
  }
176
186
  unmountDecorations('data-blocks-drag-handle-container');
177
187
 
@@ -186,7 +196,8 @@ export const dragHandleDecoration = (api, getIntl, pos, anchorName, nodeType, ha
186
196
  getPos,
187
197
  anchorName,
188
198
  nodeType,
189
- handleOptions
199
+ handleOptions,
200
+ isTopLevelNode
190
201
  })), element);
191
202
  return element;
192
203
  }, {
@@ -1,7 +1,9 @@
1
1
  import rafSchedule from 'raf-schd';
2
+ import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
2
3
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
4
  import { browser } from '@atlaskit/editor-common/browser';
4
5
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
6
+ import { isTextInput } from '@atlaskit/editor-common/utils';
5
7
  import { NodeSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
6
8
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
9
  import { fg } from '@atlaskit/platform-feature-flags';
@@ -73,13 +75,6 @@ const destroyFn = api => {
73
75
  }));
74
76
  return combine(...cleanupFn);
75
77
  };
76
- function getDocChildrenCount(newState) {
77
- let size = 0;
78
- newState.doc.descendants(node => {
79
- size += node.childCount;
80
- });
81
- return size;
82
- }
83
78
  const initialState = {
84
79
  decorations: DecorationSet.empty,
85
80
  activeNode: undefined,
@@ -124,11 +119,12 @@ export const createPlugin = (api, getIntl) => {
124
119
  exposure: true
125
120
  }) || editorExperiment('nested-dnd', true);
126
121
  let activeNodeWithNewNodeType = null;
127
- const newChildCount = tr.docChanged && editorExperiment('nested-dnd', true) ? getDocChildrenCount(newState) : childCount;
122
+ const newChildCount = tr.docChanged && editorExperiment('nested-dnd', true) ? 0 : childCount;
128
123
  // If tables or media are being resized, we want to hide the drag handle
129
124
  const resizerMeta = tr.getMeta('is-resizer-resizing');
130
125
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
131
- const nodeCountChanged = editorExperiment('nested-dnd', true) ? childCount !== newChildCount : oldState.doc.childCount !== newState.doc.childCount;
126
+ const canIgnoreTr = () => !tr.steps.every(e => e instanceof AnalyticsStep);
127
+ const nodeCountChanged = editorExperiment('nested-dnd', true) ? !isTextInput(tr) && tr.docChanged && canIgnoreTr() : oldState.doc.childCount !== newState.doc.childCount;
132
128
  const shouldRemoveHandle = !tr.getMeta('isRemote');
133
129
 
134
130
  // During resize, remove the drag handle widget so its dom positioning doesn't need to be maintained
@@ -154,10 +150,8 @@ export const createPlugin = (api, getIntl) => {
154
150
  let newNodeDecs;
155
151
  if (editorExperiment('nested-dnd', true)) {
156
152
  var _meta$isDragging;
157
- // naive solution while we work on performance optimised approach under ED-24503
158
- newNodeDecs = nodeDecorations(newState);
159
- isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && decsLength !== newNodeDecs.length;
160
- isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && nodeCountChanged;
153
+ isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && nodeCountChanged;
154
+ isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && nodeCountChanged && !(meta !== null && meta !== void 0 && meta.nodeMoved);
161
155
  } else {
162
156
  isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && decsLength !== newState.doc.childCount;
163
157
  }
@@ -178,15 +172,14 @@ export const createPlugin = (api, getIntl) => {
178
172
  // The tr.meta.activeNode is triggered by the showDragHandleAt function during the mouse entry event
179
173
  // (when the table node rerenders)
180
174
  // The activeNode is from the previous rendering cycle, and verify if they share the same anchor.
181
- const maybeTableWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 ? void 0 : (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && (isPerformanceFix || meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName));
175
+ const maybeTableWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 ? void 0 : (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName);
182
176
  const redrawDecorations = decorations === DecorationSet.empty || (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== editorHeight || (meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== editorWidthLeft || (meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== editorWidthRight || maybeWidthUpdated || nodeCountChanged || maybeTableWidthUpdated || resizerMeta === false || isDecsMissing || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
183
177
 
184
178
  // Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
185
179
  if (redrawDecorations && !isResizerResizing && api) {
186
- var _newNodeDecs;
187
180
  const oldNodeDecs = decorations.find(undefined, undefined, spec => spec.type !== 'drop-target-decoration');
188
181
  decorations = decorations.remove(oldNodeDecs);
189
- newNodeDecs = (_newNodeDecs = newNodeDecs) !== null && _newNodeDecs !== void 0 ? _newNodeDecs : nodeDecorations(newState);
182
+ newNodeDecs = nodeDecorations(newState);
190
183
  decorations = decorations.add(newState.doc, [...newNodeDecs]);
191
184
  if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved) && !isDecsMissing) {
192
185
  let mappedPosisiton = tr.mapping.map(activeNode.pos);
@@ -29,7 +29,7 @@ export const getNestedNodeLeftPaddingMargin = nodeType => {
29
29
  case 'layoutColumn':
30
30
  return '20px';
31
31
  case 'panel':
32
- return '44px';
32
+ return '40px';
33
33
  case 'tableCell':
34
34
  return '8px';
35
35
  case 'tableHeader':
@@ -67,7 +67,8 @@ const DragHandleInternal = ({
67
67
  intl: {
68
68
  formatMessage
69
69
  },
70
- handleOptions
70
+ handleOptions,
71
+ isTopLevelNode = true
71
72
  }) => {
72
73
  var _api$core2, _api$analytics2, _api$core4, _api$core6;
73
74
  const start = getPos();
@@ -341,7 +342,7 @@ const DragHandleInternal = ({
341
342
  label: "",
342
343
  size: "medium"
343
344
  }));
344
- return fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
345
+ return isTopLevelNode && fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
345
346
  content: jsx(TooltipContentWithMultipleShortcuts, {
346
347
  helpDescriptors: helpDescriptors
347
348
  }),
@@ -94,11 +94,14 @@ export const TypeAheadControl = ({
94
94
  };
95
95
  const TypeAheadControlWithIntl = injectIntl(TypeAheadControl);
96
96
  const toDOM = (api, getPos, getIntl) => {
97
+ const wrapper = document.createElement('span');
98
+ wrapper.contentEditable = 'false';
99
+ wrapper.setAttribute('data-empty-block-experiment', 'true');
100
+ wrapper.setAttribute('class', 'empty-block-experiment');
97
101
  const element = document.createElement('span');
98
102
  element.contentEditable = 'false';
99
- element.setAttribute('style', 'position: relative');
100
- element.setAttribute('class', 'empty-block-experiment');
101
- element.setAttribute('data-empty-block-experiment', 'true');
103
+ element.setAttribute('style', 'position: absolute;');
104
+ wrapper.appendChild(element);
102
105
  ReactDOM.render( /*#__PURE__*/createElement(RawIntlProvider, {
103
106
  value: getIntl()
104
107
  }, /*#__PURE__*/createElement(TypeAheadControlWithIntl, {
@@ -110,8 +113,8 @@ const toDOM = (api, getPos, getIntl) => {
110
113
  // // Cursor height cannot be controlled via CSS and is handled by the browser.
111
114
  // // see Prosemirror forum: https://discuss.prosemirror.net/t/chrome-caret-cursor-larger-than-the-text-with-inlined-items/5946
112
115
  const cursorHack = document.createTextNode(ZERO_WIDTH_SPACE);
113
- element.appendChild(cursorHack);
114
- return element;
116
+ wrapper.appendChild(cursorHack);
117
+ return wrapper;
115
118
  };
116
119
  export const createEmptyBlockWidgetDecoration = (selection, api, getIntl) => {
117
120
  if (selection instanceof TextSelection && selection.$cursor) {
@@ -163,15 +163,18 @@ export var moveNode = function moveNode(api) {
163
163
  nodeMoved: true
164
164
  });
165
165
  api === null || api === void 0 || api.core.actions.focus();
166
+ var $mappedTo = tr.doc.resolve(mappedTo);
166
167
  api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
167
168
  eventType: EVENT_TYPE.TRACK,
168
169
  action: ACTION.MOVED,
169
170
  actionSubject: ACTION_SUBJECT.ELEMENT,
170
171
  actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
171
- attributes: _objectSpread({
172
+ attributes: _objectSpread(_objectSpread({
172
173
  nodeDepth: resolvedNode.depth,
173
174
  nodeType: node.type.name
174
- }, fg('platform_editor_element_drag_and_drop_ed_23873') && {
175
+ }, editorExperiment('nested-dnd', true) && {
176
+ destinationNodeDepth: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth
177
+ }), fg('platform_editor_element_drag_and_drop_ed_23873') && {
175
178
  inputMethod: inputMethod
176
179
  })
177
180
  })(tr);
@@ -177,13 +177,23 @@ export var dragHandleDecoration = function dragHandleDecoration(api, getIntl, po
177
177
  element.style.display = 'inline';
178
178
  element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
179
179
  element.setAttribute('data-blocks-drag-handle-container', 'true');
180
+ var isTopLevelNode = true;
180
181
  if (editorExperiment('nested-dnd', true)) {
181
- unbind = bind(element, {
182
- type: 'mouseover',
183
- listener: function listener(e) {
184
- e.stopPropagation();
185
- }
186
- });
182
+ var $pos = view.state.doc.resolve(pos);
183
+ isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
184
+ /*
185
+ * We disable mouseover event to fix flickering issue on hover
186
+ * However, the tooltip for nested drag handle is not long working.
187
+ */
188
+ if (!isTopLevelNode) {
189
+ // This will also hide the tooltip.
190
+ unbind = bind(element, {
191
+ type: 'mouseover',
192
+ listener: function listener(e) {
193
+ e.stopPropagation();
194
+ }
195
+ });
196
+ }
187
197
  }
188
198
  unmountDecorations('data-blocks-drag-handle-container');
189
199
 
@@ -198,7 +208,8 @@ export var dragHandleDecoration = function dragHandleDecoration(api, getIntl, po
198
208
  getPos: getPos,
199
209
  anchorName: anchorName,
200
210
  nodeType: nodeType,
201
- handleOptions: handleOptions
211
+ handleOptions: handleOptions,
212
+ isTopLevelNode: isTopLevelNode
202
213
  })), element);
203
214
  return element;
204
215
  }, {
@@ -1,8 +1,10 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import rafSchedule from 'raf-schd';
3
+ import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
3
4
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
4
5
  import { browser } from '@atlaskit/editor-common/browser';
5
6
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
7
+ import { isTextInput } from '@atlaskit/editor-common/utils';
6
8
  import { NodeSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
7
9
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
10
  import { fg } from '@atlaskit/platform-feature-flags';
@@ -72,13 +74,6 @@ var destroyFn = function destroyFn(api) {
72
74
  }));
73
75
  return combine.apply(void 0, cleanupFn);
74
76
  };
75
- function getDocChildrenCount(newState) {
76
- var size = 0;
77
- newState.doc.descendants(function (node) {
78
- size += node.childCount;
79
- });
80
- return size;
81
- }
82
77
  var initialState = {
83
78
  decorations: DecorationSet.empty,
84
79
  activeNode: undefined,
@@ -121,11 +116,16 @@ export var createPlugin = function createPlugin(api, getIntl) {
121
116
  exposure: true
122
117
  }) || editorExperiment('nested-dnd', true);
123
118
  var activeNodeWithNewNodeType = null;
124
- var newChildCount = tr.docChanged && editorExperiment('nested-dnd', true) ? getDocChildrenCount(newState) : childCount;
119
+ var newChildCount = tr.docChanged && editorExperiment('nested-dnd', true) ? 0 : childCount;
125
120
  // If tables or media are being resized, we want to hide the drag handle
126
121
  var resizerMeta = tr.getMeta('is-resizer-resizing');
127
122
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
128
- var nodeCountChanged = editorExperiment('nested-dnd', true) ? childCount !== newChildCount : oldState.doc.childCount !== newState.doc.childCount;
123
+ var canIgnoreTr = function canIgnoreTr() {
124
+ return !tr.steps.every(function (e) {
125
+ return e instanceof AnalyticsStep;
126
+ });
127
+ };
128
+ var nodeCountChanged = editorExperiment('nested-dnd', true) ? !isTextInput(tr) && tr.docChanged && canIgnoreTr() : oldState.doc.childCount !== newState.doc.childCount;
129
129
  var shouldRemoveHandle = !tr.getMeta('isRemote');
130
130
 
131
131
  // During resize, remove the drag handle widget so its dom positioning doesn't need to be maintained
@@ -155,10 +155,8 @@ export var createPlugin = function createPlugin(api, getIntl) {
155
155
  var newNodeDecs;
156
156
  if (editorExperiment('nested-dnd', true)) {
157
157
  var _meta$isDragging;
158
- // naive solution while we work on performance optimised approach under ED-24503
159
- newNodeDecs = nodeDecorations(newState);
160
- isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && decsLength !== newNodeDecs.length;
161
- isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && nodeCountChanged;
158
+ isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && nodeCountChanged;
159
+ isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && nodeCountChanged && !(meta !== null && meta !== void 0 && meta.nodeMoved);
162
160
  } else {
163
161
  isDecsMissing = !(isDragging || meta !== null && meta !== void 0 && meta.isDragging) && decsLength !== newState.doc.childCount;
164
162
  }
@@ -180,17 +178,16 @@ export var createPlugin = function createPlugin(api, getIntl) {
180
178
  // The tr.meta.activeNode is triggered by the showDragHandleAt function during the mouse entry event
181
179
  // (when the table node rerenders)
182
180
  // The activeNode is from the previous rendering cycle, and verify if they share the same anchor.
183
- var maybeTableWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 || (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && (isPerformanceFix || meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName));
181
+ var maybeTableWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 || (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName);
184
182
  var redrawDecorations = decorations === DecorationSet.empty || (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== editorHeight || (meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== editorWidthLeft || (meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== editorWidthRight || maybeWidthUpdated || nodeCountChanged || maybeTableWidthUpdated || resizerMeta === false || isDecsMissing || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
185
183
 
186
184
  // Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
187
185
  if (redrawDecorations && !isResizerResizing && api) {
188
- var _newNodeDecs;
189
186
  var oldNodeDecs = decorations.find(undefined, undefined, function (spec) {
190
187
  return spec.type !== 'drop-target-decoration';
191
188
  });
192
189
  decorations = decorations.remove(oldNodeDecs);
193
- newNodeDecs = (_newNodeDecs = newNodeDecs) !== null && _newNodeDecs !== void 0 ? _newNodeDecs : nodeDecorations(newState);
190
+ newNodeDecs = nodeDecorations(newState);
194
191
  decorations = decorations.add(newState.doc, _toConsumableArray(newNodeDecs));
195
192
  if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved) && !isDecsMissing) {
196
193
  var mappedPosisiton = tr.mapping.map(activeNode.pos);
@@ -31,7 +31,7 @@ export var getNestedNodeLeftPaddingMargin = function getNestedNodeLeftPaddingMar
31
31
  case 'layoutColumn':
32
32
  return '20px';
33
33
  case 'panel':
34
- return '44px';
34
+ return '40px';
35
35
  case 'tableCell':
36
36
  return '8px';
37
37
  case 'tableHeader':
@@ -67,7 +67,9 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
67
67
  anchorName = _ref.anchorName,
68
68
  nodeType = _ref.nodeType,
69
69
  formatMessage = _ref.intl.formatMessage,
70
- handleOptions = _ref.handleOptions;
70
+ handleOptions = _ref.handleOptions,
71
+ _ref$isTopLevelNode = _ref.isTopLevelNode,
72
+ isTopLevelNode = _ref$isTopLevelNode === void 0 ? true : _ref$isTopLevelNode;
71
73
  var start = getPos();
72
74
  var buttonRef = useRef(null);
73
75
  var _useState = useState(768),
@@ -350,7 +352,7 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
350
352
  }))
351
353
  );
352
354
  };
353
- return fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
355
+ return isTopLevelNode && fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
354
356
  content: jsx(TooltipContentWithMultipleShortcuts, {
355
357
  helpDescriptors: helpDescriptors
356
358
  }),
@@ -91,11 +91,14 @@ export var TypeAheadControl = function TypeAheadControl(_ref) {
91
91
  };
92
92
  var TypeAheadControlWithIntl = injectIntl(TypeAheadControl);
93
93
  var toDOM = function toDOM(api, getPos, getIntl) {
94
+ var wrapper = document.createElement('span');
95
+ wrapper.contentEditable = 'false';
96
+ wrapper.setAttribute('data-empty-block-experiment', 'true');
97
+ wrapper.setAttribute('class', 'empty-block-experiment');
94
98
  var element = document.createElement('span');
95
99
  element.contentEditable = 'false';
96
- element.setAttribute('style', 'position: relative');
97
- element.setAttribute('class', 'empty-block-experiment');
98
- element.setAttribute('data-empty-block-experiment', 'true');
100
+ element.setAttribute('style', 'position: absolute;');
101
+ wrapper.appendChild(element);
99
102
  ReactDOM.render( /*#__PURE__*/createElement(RawIntlProvider, {
100
103
  value: getIntl()
101
104
  }, /*#__PURE__*/createElement(TypeAheadControlWithIntl, {
@@ -107,8 +110,8 @@ var toDOM = function toDOM(api, getPos, getIntl) {
107
110
  // // Cursor height cannot be controlled via CSS and is handled by the browser.
108
111
  // // see Prosemirror forum: https://discuss.prosemirror.net/t/chrome-caret-cursor-larger-than-the-text-with-inlined-items/5946
109
112
  var cursorHack = document.createTextNode(ZERO_WIDTH_SPACE);
110
- element.appendChild(cursorHack);
111
- return element;
113
+ wrapper.appendChild(cursorHack);
114
+ return wrapper;
112
115
  };
113
116
  export var createEmptyBlockWidgetDecoration = function createEmptyBlockWidgetDecoration(selection, api, getIntl) {
114
117
  if (selection instanceof TextSelection && selection.$cursor) {
@@ -8,7 +8,7 @@ export declare const DRAG_HANDLE_MAX_GAP = 12;
8
8
  export declare const DRAG_HANDLE_MAX_WIDTH_PLUS_GAP: number;
9
9
  export declare const DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT: number;
10
10
  export declare const dragHandleGap: (nodeType: string, parentNodeType?: string) => 4 | 8 | 12;
11
- export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "44px";
11
+ export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "40px";
12
12
  export declare const topPositionAdjustment: (nodeType: string) => number;
13
13
  /**
14
14
  * This document serves as a quick reference map for correlating various space matches
@@ -10,6 +10,7 @@ export declare const DragHandle: import("react").FC<import("react-intl-next").Wi
10
10
  anchorName: string;
11
11
  nodeType: string;
12
12
  handleOptions?: HandleOptions;
13
+ isTopLevelNode?: Boolean | undefined;
13
14
  } & WrappedComponentProps>> & {
14
15
  WrappedComponent: import("react").ComponentType<{
15
16
  view: EditorView;
@@ -18,5 +19,6 @@ export declare const DragHandle: import("react").FC<import("react-intl-next").Wi
18
19
  anchorName: string;
19
20
  nodeType: string;
20
21
  handleOptions?: HandleOptions;
22
+ isTopLevelNode?: Boolean | undefined;
21
23
  } & WrappedComponentProps>;
22
24
  };
@@ -8,7 +8,7 @@ export declare const DRAG_HANDLE_MAX_GAP = 12;
8
8
  export declare const DRAG_HANDLE_MAX_WIDTH_PLUS_GAP: number;
9
9
  export declare const DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT: number;
10
10
  export declare const dragHandleGap: (nodeType: string, parentNodeType?: string) => 4 | 8 | 12;
11
- export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "44px";
11
+ export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "40px";
12
12
  export declare const topPositionAdjustment: (nodeType: string) => number;
13
13
  /**
14
14
  * This document serves as a quick reference map for correlating various space matches
@@ -10,6 +10,7 @@ export declare const DragHandle: import("react").FC<import("react-intl-next").Wi
10
10
  anchorName: string;
11
11
  nodeType: string;
12
12
  handleOptions?: HandleOptions;
13
+ isTopLevelNode?: Boolean | undefined;
13
14
  } & WrappedComponentProps>> & {
14
15
  WrappedComponent: import("react").ComponentType<{
15
16
  view: EditorView;
@@ -18,5 +19,6 @@ export declare const DragHandle: import("react").FC<import("react-intl-next").Wi
18
19
  anchorName: string;
19
20
  nodeType: string;
20
21
  handleOptions?: HandleOptions;
22
+ isTopLevelNode?: Boolean | undefined;
21
23
  } & WrappedComponentProps>;
22
24
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -30,12 +30,13 @@
30
30
  ".": "./src/index.ts"
31
31
  },
32
32
  "dependencies": {
33
- "@atlaskit/editor-common": "^89.3.0",
33
+ "@atlaskit/adf-schema": "^40.9.0",
34
+ "@atlaskit/editor-common": "^90.0.0",
34
35
  "@atlaskit/editor-plugin-accessibility-utils": "^1.2.0",
35
36
  "@atlaskit/editor-plugin-analytics": "^1.8.0",
36
37
  "@atlaskit/editor-plugin-editor-disabled": "^1.3.0",
37
38
  "@atlaskit/editor-plugin-feature-flags": "^1.2.0",
38
- "@atlaskit/editor-plugin-quick-insert": "^1.3.0",
39
+ "@atlaskit/editor-plugin-quick-insert": "^1.4.0",
39
40
  "@atlaskit/editor-plugin-width": "^1.3.0",
40
41
  "@atlaskit/editor-prosemirror": "6.0.0",
41
42
  "@atlaskit/editor-shared-styles": "^2.13.0",