@atlaskit/editor-plugin-block-controls 1.10.2 → 1.10.3

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,16 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 1.10.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#127123](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/127123)
8
+ [`7a68ab6404094`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/7a68ab6404094) -
9
+ [ux] Add validation to node move, only show valid drop targets
10
+ - [#126802](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/126802)
11
+ [`2cd334b37d1d8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/2cd334b37d1d8) -
12
+ Clean up FFs
13
+
3
14
  ## 1.10.2
4
15
 
5
16
  ### Patch Changes
@@ -15,12 +15,14 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
15
  var _consts = require("../consts");
16
16
  var _main = require("../pm-plugins/main");
17
17
  var _utils2 = require("../utils");
18
+ var _validation = require("../utils/validation");
18
19
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
19
20
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
20
21
  function transformNested(nodeCopy, destType) {
21
- var firstChild = nodeCopy.content.firstChild;
22
- if (firstChild && firstChild.type.name === 'nestedExpand' && destType === 'doc') {
23
- return (0, _transforms.transformSliceNestedExpandToExpand)(nodeCopy, firstChild.type.schema);
22
+ var srcNode = nodeCopy.content.firstChild;
23
+ var schema = srcNode === null || srcNode === void 0 ? void 0 : srcNode.type.schema;
24
+ if (srcNode && schema && srcNode.type === schema.nodes.nestedExpand && destType === schema.nodes.doc) {
25
+ return (0, _transforms.transformSliceNestedExpandToExpand)(nodeCopy, schema);
24
26
  }
25
27
  return nodeCopy;
26
28
  }
@@ -119,7 +121,14 @@ var moveNode = exports.moveNode = function moveNode(api) {
119
121
  var mappedTo;
120
122
  if ((0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_nested')) {
121
123
  var nodeCopy = tr.doc.slice(start, end, false); // cut the content
122
- var destType = tr.doc.resolve(to).node().type.name;
124
+ var $to = tr.doc.resolve(to);
125
+ var $from = tr.doc.resolve(start);
126
+ var destType = $to.node().type;
127
+ var srcType = $from.node().child($from.index()).type;
128
+ var destParent = $to.node($to.depth);
129
+ if (!(0, _validation.canMoveToIndex)(destParent, $to.index(), srcType)) {
130
+ return tr;
131
+ }
123
132
  var convertedNode = transformNested(nodeCopy, destType).content;
124
133
  tr.delete(start, end); // delete the content from the original position
125
134
  mappedTo = tr.mapping.map(to);
@@ -15,9 +15,10 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
15
  var _dragHandle = require("../ui/drag-handle");
16
16
  var _dropTarget = require("../ui/drop-target");
17
17
  var _mouseMoveWrapper = require("../ui/mouse-move-wrapper");
18
+ var _validation = require("../utils/validation");
18
19
  var IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn'];
19
20
  var NESTED_DEPTH = (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_nested') ? 100 : 0;
20
- var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetDecorations(oldState, newState, api, formatMessage) {
21
+ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetDecorations(oldState, newState, api, formatMessage, activeNodeType) {
21
22
  var decs = [];
22
23
  unmountDecorations('data-blocks-drop-target-container');
23
24
  // Decoration state is used to keep track of the position of the drop targets
@@ -25,8 +26,9 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
25
26
  var decorationState = [];
26
27
  var prevNode;
27
28
  var state = (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_24372') ? newState : oldState;
28
- state.doc.nodesBetween(0, newState.doc.nodeSize - 2, function (node, pos, _parent, index) {
29
+ state.doc.nodesBetween(0, newState.doc.nodeSize - 2, function (node, pos, parent, index) {
29
30
  var depth = 0;
31
+ var nodeType = newState.doc.type.schema.nodes[activeNodeType];
30
32
  if ((0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_nested')) {
31
33
  depth = newState.doc.resolve(pos).depth;
32
34
  if (node.isInline) {
@@ -35,6 +37,12 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
35
37
  if (IGNORE_NODES.includes(node.type.name)) {
36
38
  return true; //skip over, don't consider it a valid depth
37
39
  }
40
+ var canDrop = parent && activeNodeType && (0, _validation.canMoveToIndex)(parent, index, nodeType);
41
+
42
+ //NOTE: This will block drop targets showing for nodes that are valid after transformation (i.e. expand -> nestedExpand)
43
+ if (!canDrop) {
44
+ return false; //not valid pos, so nested not valid either
45
+ }
38
46
  decorationState.push({
39
47
  id: pos,
40
48
  pos: pos
@@ -94,7 +94,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
94
94
  return initialState;
95
95
  },
96
96
  apply: function apply(tr, currentState, oldState, newState) {
97
- var _meta$activeNode, _meta$activeNode$hand, _meta$activeNode2, _meta$isDragging, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
97
+ var _meta$activeNode, _meta$activeNode$hand, _meta$activeNode4, _meta$isDragging, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
98
98
  if (initialState.isDocSizeLimitEnabled === null) {
99
99
  if ((0, _platformFeatureFlags.fg)('platform.editor.elements.drag-and-drop-doc-size-limit_7k4vq')) {
100
100
  initialState.isDocSizeLimitEnabled = true;
@@ -275,7 +275,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
275
275
  // Add drop targets when node is being dragged
276
276
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
277
277
  if (shouldUpdateDropTargets || (0, _dragTargetDebug.isBlocksDragTargetDebug)()) {
278
- var _dropTargetDecoration = (0, _decorations.dropTargetDecorations)(oldState, newState, api, formatMessage),
278
+ var _meta$activeNode2;
279
+ var _dropTargetDecoration = (0, _decorations.dropTargetDecorations)(oldState, newState, api, formatMessage, meta === null || meta === void 0 || (_meta$activeNode2 = meta.activeNode) === null || _meta$activeNode2 === void 0 ? void 0 : _meta$activeNode2.nodeType),
279
280
  _decs2 = _dropTargetDecoration.decs,
280
281
  updatedDecorationState = _dropTargetDecoration.decorationState;
281
282
  decorationState = updatedDecorationState;
@@ -300,7 +301,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
300
301
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
301
302
  var shouldShowDragTarget = (meta === null || meta === void 0 ? void 0 : meta.isDragging) && (!tr.docChanged || tr.docChanged && isAnalyticTr);
302
303
  if (shouldShowDragTarget || (0, _dragTargetDebug.isBlocksDragTargetDebug)()) {
303
- var _dropTargetDecoration2 = (0, _decorations.dropTargetDecorations)(oldState, newState, api, formatMessage),
304
+ var _meta$activeNode3;
305
+ var _dropTargetDecoration2 = (0, _decorations.dropTargetDecorations)(oldState, newState, api, formatMessage, meta === null || meta === void 0 || (_meta$activeNode3 = meta.activeNode) === null || _meta$activeNode3 === void 0 ? void 0 : _meta$activeNode3.nodeType),
304
306
  _decs3 = _dropTargetDecoration2.decs,
305
307
  _updatedDecorationState = _dropTargetDecoration2.decorationState;
306
308
  decorationState = _updatedDecorationState;
@@ -361,7 +363,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl) {
361
363
  return {
362
364
  decorations: decorations,
363
365
  decorationState: decorationState,
364
- activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode2 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode2 !== void 0 ? _meta$activeNode2 : mappedActiveNodePos,
366
+ activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode4 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode4 !== void 0 ? _meta$activeNode4 : mappedActiveNodePos,
365
367
  isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging,
366
368
  isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
367
369
  editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
@@ -90,30 +90,15 @@ var extendedHoverZoneNested = (0, _react.css)({
90
90
  display: 'none'
91
91
  }
92
92
  });
93
- var paragraphWithTrailingBreak = '+ p > .ProseMirror-trailingBreak';
94
- var paragraphWithCursorTarget = '+ p > .cursor-target';
95
93
  var paragraphWithTrailingBreakAsOnlyChild = '+ p > .ProseMirror-trailingBreak:only-child';
96
94
  var paragraphWithPlaceholder = '+ p > .placeholder-decoration';
97
95
  var dragHandleContainer = '.ProseMirror-widget[data-blocks-drag-handle-container="true"]';
98
96
  var dragHandleSelector = 'button[data-testid="block-ctrl-drag-handle"]';
99
- var withoutInlineNodeStyle = (0, _react.css)((0, _defineProperty2.default)({}, ".ProseMirror-widget[data-blocks-drag-handle-container=\"true\"]:has(".concat(paragraphWithTrailingBreak, "):not(:has(").concat(paragraphWithCursorTarget, "))"), {
100
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
101
- display: 'none !important'
102
- }));
103
97
  var withInlineNodeStyle = (0, _react.css)((0, _defineProperty2.default)({}, ".ProseMirror-widget[data-blocks-drag-handle-container=\"true\"]:has(".concat(paragraphWithTrailingBreakAsOnlyChild, "), .ProseMirror-widget[data-blocks-drag-handle-container=\"true\"]:has(").concat(paragraphWithPlaceholder, ")"), {
104
98
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
105
99
  display: 'none !important'
106
100
  }));
107
101
 
108
- /**
109
- * Please do not change change transform to display:none, or visibility:hidden
110
- * Otherwise it might break composition input for Chrome
111
- * https://product-fabric.atlassian.net/browse/ED-24136
112
- */
113
- var withoutInlineNodeStyleWithChromeFix = (0, _react.css)((0, _defineProperty2.default)({}, "".concat(dragHandleContainer, ":has(").concat(paragraphWithTrailingBreak, "):not(:has(").concat(paragraphWithCursorTarget, ")) ").concat(dragHandleSelector), {
114
- transform: 'scale(0)'
115
- }));
116
-
117
102
  /**
118
103
  * Please do not change change transform to display:none, or visibility:hidden
119
104
  * Otherwise it might break composition input for Chrome
@@ -141,14 +126,10 @@ var withMediaSingleStyleFix = (0, _react.css)((0, _defineProperty2.default)({},
141
126
  cursor: 'pointer'
142
127
  }));
143
128
  var getTextNodeStyle = function getTextNodeStyle() {
144
- if ((0, _platformFeatureFlags.fg)('platform.editor.elements.drag-and-drop-ed-23868')) {
145
- return (0, _platformFeatureFlags.fg)('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
146
- } else {
147
- return (0, _platformFeatureFlags.fg)('platform_editor_element_controls_chrome_input_fix') ? withoutInlineNodeStyleWithChromeFix : withoutInlineNodeStyle;
148
- }
129
+ return (0, _platformFeatureFlags.fg)('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
149
130
  };
150
131
  var GlobalStylesWrapper = exports.GlobalStylesWrapper = function GlobalStylesWrapper() {
151
132
  return (0, _react.jsx)(_react.Global, {
152
- styles: [globalStyles, (0, _platformFeatureFlags.fg)('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_nested') ? extendedHoverZoneNested : extendedHoverZone : false, getTextNodeStyle(), (0, _platformFeatureFlags.fg)('platform.editor.elements.drag-and-drop-ed-23932') && withDeleteLinesStyleFix, (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_24005') && withMediaSingleStyleFix]
133
+ styles: [globalStyles, (0, _platformFeatureFlags.fg)('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_nested') ? extendedHoverZoneNested : extendedHoverZone : false, getTextNodeStyle(), withDeleteLinesStyleFix, withMediaSingleStyleFix]
153
134
  });
154
135
  };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.canMoveToIndex = canMoveToIndex;
7
+ function canMoveToIndex(destParent, indexIntoParent, srcType) {
8
+ return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcType);
9
+ }
@@ -7,10 +7,12 @@ import { fg } from '@atlaskit/platform-feature-flags';
7
7
  import { DIRECTION } from '../consts';
8
8
  import { key } from '../pm-plugins/main';
9
9
  import { selectNode } from '../utils';
10
+ import { canMoveToIndex } from '../utils/validation';
10
11
  function transformNested(nodeCopy, destType) {
11
- const firstChild = nodeCopy.content.firstChild;
12
- if (firstChild && firstChild.type.name === 'nestedExpand' && destType === 'doc') {
13
- return transformSliceNestedExpandToExpand(nodeCopy, firstChild.type.schema);
12
+ const srcNode = nodeCopy.content.firstChild;
13
+ const schema = srcNode === null || srcNode === void 0 ? void 0 : srcNode.type.schema;
14
+ if (srcNode && schema && srcNode.type === schema.nodes.nestedExpand && destType === schema.nodes.doc) {
15
+ return transformSliceNestedExpandToExpand(nodeCopy, schema);
14
16
  }
15
17
  return nodeCopy;
16
18
  }
@@ -111,7 +113,14 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
111
113
  let mappedTo;
112
114
  if (fg('platform_editor_elements_dnd_nested')) {
113
115
  const nodeCopy = tr.doc.slice(start, end, false); // cut the content
114
- const destType = tr.doc.resolve(to).node().type.name;
116
+ const $to = tr.doc.resolve(to);
117
+ const $from = tr.doc.resolve(start);
118
+ const destType = $to.node().type;
119
+ const srcType = $from.node().child($from.index()).type;
120
+ const destParent = $to.node($to.depth);
121
+ if (!canMoveToIndex(destParent, $to.index(), srcType)) {
122
+ return tr;
123
+ }
115
124
  const convertedNode = transformNested(nodeCopy, destType).content;
116
125
  tr.delete(start, end); // delete the content from the original position
117
126
  mappedTo = tr.mapping.map(to);
@@ -7,9 +7,10 @@ import { fg } from '@atlaskit/platform-feature-flags';
7
7
  import { DragHandle } from '../ui/drag-handle';
8
8
  import { DropTarget } from '../ui/drop-target';
9
9
  import { MouseMoveWrapper } from '../ui/mouse-move-wrapper';
10
+ import { canMoveToIndex } from '../utils/validation';
10
11
  const IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn'];
11
12
  const NESTED_DEPTH = fg('platform_editor_elements_dnd_nested') ? 100 : 0;
12
- export const dropTargetDecorations = (oldState, newState, api, formatMessage) => {
13
+ export const dropTargetDecorations = (oldState, newState, api, formatMessage, activeNodeType) => {
13
14
  const decs = [];
14
15
  unmountDecorations('data-blocks-drop-target-container');
15
16
  // Decoration state is used to keep track of the position of the drop targets
@@ -17,8 +18,9 @@ export const dropTargetDecorations = (oldState, newState, api, formatMessage) =>
17
18
  const decorationState = [];
18
19
  let prevNode;
19
20
  const state = fg('platform_editor_element_drag_and_drop_ed_24372') ? newState : oldState;
20
- state.doc.nodesBetween(0, newState.doc.nodeSize - 2, (node, pos, _parent, index) => {
21
+ state.doc.nodesBetween(0, newState.doc.nodeSize - 2, (node, pos, parent, index) => {
21
22
  let depth = 0;
23
+ const nodeType = newState.doc.type.schema.nodes[activeNodeType];
22
24
  if (fg('platform_editor_elements_dnd_nested')) {
23
25
  depth = newState.doc.resolve(pos).depth;
24
26
  if (node.isInline) {
@@ -27,6 +29,12 @@ export const dropTargetDecorations = (oldState, newState, api, formatMessage) =>
27
29
  if (IGNORE_NODES.includes(node.type.name)) {
28
30
  return true; //skip over, don't consider it a valid depth
29
31
  }
32
+ const canDrop = parent && activeNodeType && canMoveToIndex(parent, index, nodeType);
33
+
34
+ //NOTE: This will block drop targets showing for nodes that are valid after transformation (i.e. expand -> nestedExpand)
35
+ if (!canDrop) {
36
+ return false; //not valid pos, so nested not valid either
37
+ }
30
38
  decorationState.push({
31
39
  id: pos,
32
40
  pos
@@ -88,7 +88,7 @@ export const createPlugin = (api, getIntl) => {
88
88
  return initialState;
89
89
  },
90
90
  apply(tr, currentState, oldState, newState) {
91
- var _meta$activeNode, _meta$activeNode$hand, _meta$activeNode2, _meta$isDragging, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
91
+ var _meta$activeNode, _meta$activeNode$hand, _meta$activeNode4, _meta$isDragging, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
92
92
  if (initialState.isDocSizeLimitEnabled === null) {
93
93
  if (fg('platform.editor.elements.drag-and-drop-doc-size-limit_7k4vq')) {
94
94
  initialState.isDocSizeLimitEnabled = true;
@@ -262,10 +262,11 @@ export const createPlugin = (api, getIntl) => {
262
262
  // Add drop targets when node is being dragged
263
263
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
264
264
  if (shouldUpdateDropTargets || isBlocksDragTargetDebug()) {
265
+ var _meta$activeNode2;
265
266
  const {
266
267
  decs,
267
268
  decorationState: updatedDecorationState
268
- } = dropTargetDecorations(oldState, newState, api, formatMessage);
269
+ } = dropTargetDecorations(oldState, newState, api, formatMessage, meta === null || meta === void 0 ? void 0 : (_meta$activeNode2 = meta.activeNode) === null || _meta$activeNode2 === void 0 ? void 0 : _meta$activeNode2.nodeType);
269
270
  decorationState = updatedDecorationState;
270
271
  decorations = decorations.add(newState.doc, decs);
271
272
  }
@@ -289,10 +290,11 @@ export const createPlugin = (api, getIntl) => {
289
290
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
290
291
  const shouldShowDragTarget = (meta === null || meta === void 0 ? void 0 : meta.isDragging) && (!tr.docChanged || tr.docChanged && isAnalyticTr);
291
292
  if (shouldShowDragTarget || isBlocksDragTargetDebug()) {
293
+ var _meta$activeNode3;
292
294
  const {
293
295
  decs,
294
296
  decorationState: updatedDecorationState
295
- } = dropTargetDecorations(oldState, newState, api, formatMessage);
297
+ } = dropTargetDecorations(oldState, newState, api, formatMessage, meta === null || meta === void 0 ? void 0 : (_meta$activeNode3 = meta.activeNode) === null || _meta$activeNode3 === void 0 ? void 0 : _meta$activeNode3.nodeType);
296
298
  decorationState = updatedDecorationState;
297
299
  decorations = decorations.add(newState.doc, decs);
298
300
  }
@@ -350,7 +352,7 @@ export const createPlugin = (api, getIntl) => {
350
352
  return {
351
353
  decorations,
352
354
  decorationState,
353
- activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode2 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode2 !== void 0 ? _meta$activeNode2 : mappedActiveNodePos,
355
+ activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode4 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode4 !== void 0 ? _meta$activeNode4 : mappedActiveNodePos,
354
356
  isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging,
355
357
  isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
356
358
  editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
@@ -81,21 +81,10 @@ const extendedHoverZoneNested = css({
81
81
  display: 'none'
82
82
  }
83
83
  });
84
- const paragraphWithTrailingBreak = '+ p > .ProseMirror-trailingBreak';
85
- const paragraphWithCursorTarget = '+ p > .cursor-target';
86
84
  const paragraphWithTrailingBreakAsOnlyChild = '+ p > .ProseMirror-trailingBreak:only-child';
87
85
  const paragraphWithPlaceholder = '+ p > .placeholder-decoration';
88
86
  const dragHandleContainer = '.ProseMirror-widget[data-blocks-drag-handle-container="true"]';
89
87
  const dragHandleSelector = 'button[data-testid="block-ctrl-drag-handle"]';
90
- const withoutInlineNodeStyle = css({
91
- // Currently, we are hiding the drag handle container by checking if the paragraph has a trailing break and no cursor target
92
- // TODO ED-23827 add a classname to empty paragraphs for easier targeting
93
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-values
94
- [`.ProseMirror-widget[data-blocks-drag-handle-container="true"]:has(${paragraphWithTrailingBreak}):not(:has(${paragraphWithCursorTarget}))`]: {
95
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
96
- display: 'none !important'
97
- }
98
- });
99
88
  const withInlineNodeStyle = css({
100
89
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-values
101
90
  [`.ProseMirror-widget[data-blocks-drag-handle-container="true"]:has(${paragraphWithTrailingBreakAsOnlyChild}), .ProseMirror-widget[data-blocks-drag-handle-container="true"]:has(${paragraphWithPlaceholder})`]: {
@@ -104,20 +93,6 @@ const withInlineNodeStyle = css({
104
93
  }
105
94
  });
106
95
 
107
- /**
108
- * Please do not change change transform to display:none, or visibility:hidden
109
- * Otherwise it might break composition input for Chrome
110
- * https://product-fabric.atlassian.net/browse/ED-24136
111
- */
112
- const withoutInlineNodeStyleWithChromeFix = css({
113
- // Currently, we are hiding the drag handle container by checking if the paragraph has a trailing break and no cursor target
114
- // TODO ED-23827 add a classname to empty paragraphs for easier targeting
115
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-values
116
- [`${dragHandleContainer}:has(${paragraphWithTrailingBreak}):not(:has(${paragraphWithCursorTarget})) ${dragHandleSelector}`]: {
117
- transform: 'scale(0)'
118
- }
119
- });
120
-
121
96
  /**
122
97
  * Please do not change change transform to display:none, or visibility:hidden
123
98
  * Otherwise it might break composition input for Chrome
@@ -155,14 +130,10 @@ const withMediaSingleStyleFix = css({
155
130
  }
156
131
  });
157
132
  const getTextNodeStyle = () => {
158
- if (fg('platform.editor.elements.drag-and-drop-ed-23868')) {
159
- return fg('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
160
- } else {
161
- return fg('platform_editor_element_controls_chrome_input_fix') ? withoutInlineNodeStyleWithChromeFix : withoutInlineNodeStyle;
162
- }
133
+ return fg('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
163
134
  };
164
135
  export const GlobalStylesWrapper = () => {
165
136
  return jsx(Global, {
166
- styles: [globalStyles, fg('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? fg('platform_editor_elements_dnd_nested') ? extendedHoverZoneNested : extendedHoverZone : false, getTextNodeStyle(), fg('platform.editor.elements.drag-and-drop-ed-23932') && withDeleteLinesStyleFix, fg('platform_editor_element_drag_and_drop_ed_24005') && withMediaSingleStyleFix]
137
+ styles: [globalStyles, fg('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? fg('platform_editor_elements_dnd_nested') ? extendedHoverZoneNested : extendedHoverZone : false, getTextNodeStyle(), withDeleteLinesStyleFix, withMediaSingleStyleFix]
167
138
  });
168
139
  };
@@ -0,0 +1,3 @@
1
+ export function canMoveToIndex(destParent, indexIntoParent, srcType) {
2
+ return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcType);
3
+ }
@@ -10,10 +10,12 @@ import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { DIRECTION } from '../consts';
11
11
  import { key } from '../pm-plugins/main';
12
12
  import { selectNode } from '../utils';
13
+ import { canMoveToIndex } from '../utils/validation';
13
14
  function transformNested(nodeCopy, destType) {
14
- var firstChild = nodeCopy.content.firstChild;
15
- if (firstChild && firstChild.type.name === 'nestedExpand' && destType === 'doc') {
16
- return transformSliceNestedExpandToExpand(nodeCopy, firstChild.type.schema);
15
+ var srcNode = nodeCopy.content.firstChild;
16
+ var schema = srcNode === null || srcNode === void 0 ? void 0 : srcNode.type.schema;
17
+ if (srcNode && schema && srcNode.type === schema.nodes.nestedExpand && destType === schema.nodes.doc) {
18
+ return transformSliceNestedExpandToExpand(nodeCopy, schema);
17
19
  }
18
20
  return nodeCopy;
19
21
  }
@@ -112,7 +114,14 @@ export var moveNode = function moveNode(api) {
112
114
  var mappedTo;
113
115
  if (fg('platform_editor_elements_dnd_nested')) {
114
116
  var nodeCopy = tr.doc.slice(start, end, false); // cut the content
115
- var destType = tr.doc.resolve(to).node().type.name;
117
+ var $to = tr.doc.resolve(to);
118
+ var $from = tr.doc.resolve(start);
119
+ var destType = $to.node().type;
120
+ var srcType = $from.node().child($from.index()).type;
121
+ var destParent = $to.node($to.depth);
122
+ if (!canMoveToIndex(destParent, $to.index(), srcType)) {
123
+ return tr;
124
+ }
116
125
  var convertedNode = transformNested(nodeCopy, destType).content;
117
126
  tr.delete(start, end); // delete the content from the original position
118
127
  mappedTo = tr.mapping.map(to);
@@ -8,9 +8,10 @@ import { fg } from '@atlaskit/platform-feature-flags';
8
8
  import { DragHandle } from '../ui/drag-handle';
9
9
  import { DropTarget } from '../ui/drop-target';
10
10
  import { MouseMoveWrapper } from '../ui/mouse-move-wrapper';
11
+ import { canMoveToIndex } from '../utils/validation';
11
12
  var IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn'];
12
13
  var NESTED_DEPTH = fg('platform_editor_elements_dnd_nested') ? 100 : 0;
13
- export var dropTargetDecorations = function dropTargetDecorations(oldState, newState, api, formatMessage) {
14
+ export var dropTargetDecorations = function dropTargetDecorations(oldState, newState, api, formatMessage, activeNodeType) {
14
15
  var decs = [];
15
16
  unmountDecorations('data-blocks-drop-target-container');
16
17
  // Decoration state is used to keep track of the position of the drop targets
@@ -18,8 +19,9 @@ export var dropTargetDecorations = function dropTargetDecorations(oldState, newS
18
19
  var decorationState = [];
19
20
  var prevNode;
20
21
  var state = fg('platform_editor_element_drag_and_drop_ed_24372') ? newState : oldState;
21
- state.doc.nodesBetween(0, newState.doc.nodeSize - 2, function (node, pos, _parent, index) {
22
+ state.doc.nodesBetween(0, newState.doc.nodeSize - 2, function (node, pos, parent, index) {
22
23
  var depth = 0;
24
+ var nodeType = newState.doc.type.schema.nodes[activeNodeType];
23
25
  if (fg('platform_editor_elements_dnd_nested')) {
24
26
  depth = newState.doc.resolve(pos).depth;
25
27
  if (node.isInline) {
@@ -28,6 +30,12 @@ export var dropTargetDecorations = function dropTargetDecorations(oldState, newS
28
30
  if (IGNORE_NODES.includes(node.type.name)) {
29
31
  return true; //skip over, don't consider it a valid depth
30
32
  }
33
+ var canDrop = parent && activeNodeType && canMoveToIndex(parent, index, nodeType);
34
+
35
+ //NOTE: This will block drop targets showing for nodes that are valid after transformation (i.e. expand -> nestedExpand)
36
+ if (!canDrop) {
37
+ return false; //not valid pos, so nested not valid either
38
+ }
31
39
  decorationState.push({
32
40
  id: pos,
33
41
  pos: pos
@@ -87,7 +87,7 @@ export var createPlugin = function createPlugin(api, getIntl) {
87
87
  return initialState;
88
88
  },
89
89
  apply: function apply(tr, currentState, oldState, newState) {
90
- var _meta$activeNode, _meta$activeNode$hand, _meta$activeNode2, _meta$isDragging, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
90
+ var _meta$activeNode, _meta$activeNode$hand, _meta$activeNode4, _meta$isDragging, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
91
91
  if (initialState.isDocSizeLimitEnabled === null) {
92
92
  if (fg('platform.editor.elements.drag-and-drop-doc-size-limit_7k4vq')) {
93
93
  initialState.isDocSizeLimitEnabled = true;
@@ -268,7 +268,8 @@ export var createPlugin = function createPlugin(api, getIntl) {
268
268
  // Add drop targets when node is being dragged
269
269
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
270
270
  if (shouldUpdateDropTargets || isBlocksDragTargetDebug()) {
271
- var _dropTargetDecoration = dropTargetDecorations(oldState, newState, api, formatMessage),
271
+ var _meta$activeNode2;
272
+ var _dropTargetDecoration = dropTargetDecorations(oldState, newState, api, formatMessage, meta === null || meta === void 0 || (_meta$activeNode2 = meta.activeNode) === null || _meta$activeNode2 === void 0 ? void 0 : _meta$activeNode2.nodeType),
272
273
  _decs2 = _dropTargetDecoration.decs,
273
274
  updatedDecorationState = _dropTargetDecoration.decorationState;
274
275
  decorationState = updatedDecorationState;
@@ -293,7 +294,8 @@ export var createPlugin = function createPlugin(api, getIntl) {
293
294
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
294
295
  var shouldShowDragTarget = (meta === null || meta === void 0 ? void 0 : meta.isDragging) && (!tr.docChanged || tr.docChanged && isAnalyticTr);
295
296
  if (shouldShowDragTarget || isBlocksDragTargetDebug()) {
296
- var _dropTargetDecoration2 = dropTargetDecorations(oldState, newState, api, formatMessage),
297
+ var _meta$activeNode3;
298
+ var _dropTargetDecoration2 = dropTargetDecorations(oldState, newState, api, formatMessage, meta === null || meta === void 0 || (_meta$activeNode3 = meta.activeNode) === null || _meta$activeNode3 === void 0 ? void 0 : _meta$activeNode3.nodeType),
297
299
  _decs3 = _dropTargetDecoration2.decs,
298
300
  _updatedDecorationState = _dropTargetDecoration2.decorationState;
299
301
  decorationState = _updatedDecorationState;
@@ -354,7 +356,7 @@ export var createPlugin = function createPlugin(api, getIntl) {
354
356
  return {
355
357
  decorations: decorations,
356
358
  decorationState: decorationState,
357
- activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode2 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode2 !== void 0 ? _meta$activeNode2 : mappedActiveNodePos,
359
+ activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode4 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode4 !== void 0 ? _meta$activeNode4 : mappedActiveNodePos,
358
360
  isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging,
359
361
  isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
360
362
  editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
@@ -82,30 +82,15 @@ var extendedHoverZoneNested = css({
82
82
  display: 'none'
83
83
  }
84
84
  });
85
- var paragraphWithTrailingBreak = '+ p > .ProseMirror-trailingBreak';
86
- var paragraphWithCursorTarget = '+ p > .cursor-target';
87
85
  var paragraphWithTrailingBreakAsOnlyChild = '+ p > .ProseMirror-trailingBreak:only-child';
88
86
  var paragraphWithPlaceholder = '+ p > .placeholder-decoration';
89
87
  var dragHandleContainer = '.ProseMirror-widget[data-blocks-drag-handle-container="true"]';
90
88
  var dragHandleSelector = 'button[data-testid="block-ctrl-drag-handle"]';
91
- var withoutInlineNodeStyle = css(_defineProperty({}, ".ProseMirror-widget[data-blocks-drag-handle-container=\"true\"]:has(".concat(paragraphWithTrailingBreak, "):not(:has(").concat(paragraphWithCursorTarget, "))"), {
92
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
93
- display: 'none !important'
94
- }));
95
89
  var withInlineNodeStyle = css(_defineProperty({}, ".ProseMirror-widget[data-blocks-drag-handle-container=\"true\"]:has(".concat(paragraphWithTrailingBreakAsOnlyChild, "), .ProseMirror-widget[data-blocks-drag-handle-container=\"true\"]:has(").concat(paragraphWithPlaceholder, ")"), {
96
90
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
97
91
  display: 'none !important'
98
92
  }));
99
93
 
100
- /**
101
- * Please do not change change transform to display:none, or visibility:hidden
102
- * Otherwise it might break composition input for Chrome
103
- * https://product-fabric.atlassian.net/browse/ED-24136
104
- */
105
- var withoutInlineNodeStyleWithChromeFix = css(_defineProperty({}, "".concat(dragHandleContainer, ":has(").concat(paragraphWithTrailingBreak, "):not(:has(").concat(paragraphWithCursorTarget, ")) ").concat(dragHandleSelector), {
106
- transform: 'scale(0)'
107
- }));
108
-
109
94
  /**
110
95
  * Please do not change change transform to display:none, or visibility:hidden
111
96
  * Otherwise it might break composition input for Chrome
@@ -133,14 +118,10 @@ var withMediaSingleStyleFix = css(_defineProperty({}, '.ProseMirror.ua-firefox .
133
118
  cursor: 'pointer'
134
119
  }));
135
120
  var getTextNodeStyle = function getTextNodeStyle() {
136
- if (fg('platform.editor.elements.drag-and-drop-ed-23868')) {
137
- return fg('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
138
- } else {
139
- return fg('platform_editor_element_controls_chrome_input_fix') ? withoutInlineNodeStyleWithChromeFix : withoutInlineNodeStyle;
140
- }
121
+ return fg('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
141
122
  };
142
123
  export var GlobalStylesWrapper = function GlobalStylesWrapper() {
143
124
  return jsx(Global, {
144
- styles: [globalStyles, fg('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? fg('platform_editor_elements_dnd_nested') ? extendedHoverZoneNested : extendedHoverZone : false, getTextNodeStyle(), fg('platform.editor.elements.drag-and-drop-ed-23932') && withDeleteLinesStyleFix, fg('platform_editor_element_drag_and_drop_ed_24005') && withMediaSingleStyleFix]
125
+ styles: [globalStyles, fg('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? fg('platform_editor_elements_dnd_nested') ? extendedHoverZoneNested : extendedHoverZone : false, getTextNodeStyle(), withDeleteLinesStyleFix, withMediaSingleStyleFix]
145
126
  });
146
127
  };
@@ -0,0 +1,3 @@
1
+ export function canMoveToIndex(destParent, indexIntoParent, srcType) {
2
+ return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcType);
3
+ }
@@ -3,7 +3,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
3
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
4
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { BlockControlsPlugin, HandleOptions } from '../types';
6
- export declare const dropTargetDecorations: (oldState: EditorState, newState: EditorState, api: ExtractInjectionAPI<BlockControlsPlugin>, formatMessage: IntlShape['formatMessage']) => {
6
+ export declare const dropTargetDecorations: (oldState: EditorState, newState: EditorState, api: ExtractInjectionAPI<BlockControlsPlugin>, formatMessage: IntlShape['formatMessage'], activeNodeType: string) => {
7
7
  decs: Decoration[];
8
8
  decorationState: {
9
9
  id: number;
@@ -0,0 +1,2 @@
1
+ import type { NodeType, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
+ export declare function canMoveToIndex(destParent: PMNode, indexIntoParent: number, srcType: NodeType): boolean;
@@ -3,7 +3,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
3
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
4
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { BlockControlsPlugin, HandleOptions } from '../types';
6
- export declare const dropTargetDecorations: (oldState: EditorState, newState: EditorState, api: ExtractInjectionAPI<BlockControlsPlugin>, formatMessage: IntlShape['formatMessage']) => {
6
+ export declare const dropTargetDecorations: (oldState: EditorState, newState: EditorState, api: ExtractInjectionAPI<BlockControlsPlugin>, formatMessage: IntlShape['formatMessage'], activeNodeType: string) => {
7
7
  decs: Decoration[];
8
8
  decorationState: {
9
9
  id: number;
@@ -0,0 +1,2 @@
1
+ import type { NodeType, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
+ export declare function canMoveToIndex(destParent: PMNode, indexIntoParent: number, srcType: NodeType): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "1.10.2",
3
+ "version": "1.10.3",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -41,13 +41,13 @@
41
41
  "@atlaskit/editor-prosemirror": "5.0.1",
42
42
  "@atlaskit/editor-shared-styles": "^2.13.0",
43
43
  "@atlaskit/editor-tables": "^2.8.0",
44
- "@atlaskit/icon": "^22.9.0",
44
+ "@atlaskit/icon": "^22.10.0",
45
45
  "@atlaskit/platform-feature-flags": "^0.3.0",
46
46
  "@atlaskit/pragmatic-drag-and-drop": "^1.2.0",
47
47
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^1.4.0",
48
48
  "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^1.1.0",
49
49
  "@atlaskit/theme": "^12.11.0",
50
- "@atlaskit/tokens": "^1.56.0",
50
+ "@atlaskit/tokens": "^1.57.0",
51
51
  "@atlaskit/tooltip": "^18.5.0",
52
52
  "@babel/runtime": "^7.0.0",
53
53
  "@emotion/react": "^11.7.1",
@@ -98,9 +98,6 @@
98
98
  "platform.editor.elements.drag-and-drop-doc-size-limit_7k4vq": {
99
99
  "type": "boolean"
100
100
  },
101
- "platform.editor.elements.drag-and-drop-ed-23868": {
102
- "type": "boolean"
103
- },
104
101
  "platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2": {
105
102
  "type": "boolean"
106
103
  },
@@ -126,9 +123,6 @@
126
123
  "platform_editor_elements_drag_and_drop_ed_23189": {
127
124
  "type": "boolean"
128
125
  },
129
- "platform.editor.elements.drag-and-drop-ed-23932": {
130
- "type": "boolean"
131
- },
132
126
  "platform_editor_elements_dnd_ed_23674": {
133
127
  "type": "boolean"
134
128
  },
@@ -147,9 +141,6 @@
147
141
  "platform_editor_element_drag_and_drop_ed_23896": {
148
142
  "type": "boolean"
149
143
  },
150
- "platform_editor_element_drag_and_drop_ed_24005": {
151
- "type": "boolean"
152
- },
153
144
  "platform_editor_element_controls_chrome_input_fix": {
154
145
  "type": "boolean"
155
146
  },