@atlaskit/editor-plugin-block-controls 2.4.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/cjs/commands/move-node.js +7 -6
  3. package/dist/cjs/commands/show-drag-handle.js +2 -1
  4. package/dist/cjs/pm-plugins/decorations.js +93 -32
  5. package/dist/cjs/pm-plugins/keymap.js +5 -2
  6. package/dist/cjs/pm-plugins/main.js +349 -203
  7. package/dist/cjs/ui/drag-handle.js +4 -6
  8. package/dist/cjs/ui/drop-target-v2.js +32 -6
  9. package/dist/cjs/ui/drop-target.js +2 -0
  10. package/dist/cjs/ui/global-styles.js +1 -7
  11. package/dist/cjs/utils/transactions.js +63 -0
  12. package/dist/cjs/utils/validation.js +17 -0
  13. package/dist/es2019/commands/move-node.js +7 -6
  14. package/dist/es2019/commands/show-drag-handle.js +2 -1
  15. package/dist/es2019/pm-plugins/decorations.js +86 -31
  16. package/dist/es2019/pm-plugins/keymap.js +5 -2
  17. package/dist/es2019/pm-plugins/main.js +332 -179
  18. package/dist/es2019/ui/drag-handle.js +4 -8
  19. package/dist/es2019/ui/drop-target-v2.js +32 -6
  20. package/dist/es2019/ui/drop-target.js +2 -0
  21. package/dist/es2019/ui/global-styles.js +1 -7
  22. package/dist/es2019/utils/transactions.js +57 -0
  23. package/dist/es2019/utils/validation.js +17 -0
  24. package/dist/esm/commands/move-node.js +7 -6
  25. package/dist/esm/commands/show-drag-handle.js +2 -1
  26. package/dist/esm/pm-plugins/decorations.js +92 -31
  27. package/dist/esm/pm-plugins/keymap.js +5 -2
  28. package/dist/esm/pm-plugins/main.js +350 -204
  29. package/dist/esm/ui/drag-handle.js +4 -6
  30. package/dist/esm/ui/drop-target-v2.js +32 -6
  31. package/dist/esm/ui/drop-target.js +2 -0
  32. package/dist/esm/ui/global-styles.js +1 -7
  33. package/dist/esm/utils/transactions.js +57 -0
  34. package/dist/esm/utils/validation.js +17 -0
  35. package/dist/types/pm-plugins/decorations.d.ts +24 -4
  36. package/dist/types/pm-plugins/main.d.ts +32 -0
  37. package/dist/types/ui/drag-handle.d.ts +5 -14
  38. package/dist/types/ui/drop-target-v2.d.ts +1 -1
  39. package/dist/types/ui/drop-target.d.ts +2 -0
  40. package/dist/types/utils/transactions.d.ts +29 -0
  41. package/dist/types-ts4.5/pm-plugins/decorations.d.ts +24 -4
  42. package/dist/types-ts4.5/pm-plugins/main.d.ts +32 -0
  43. package/dist/types-ts4.5/ui/drag-handle.d.ts +5 -14
  44. package/dist/types-ts4.5/ui/drop-target-v2.d.ts +1 -1
  45. package/dist/types-ts4.5/ui/drop-target.d.ts +2 -0
  46. package/dist/types-ts4.5/utils/transactions.d.ts +29 -0
  47. package/package.json +5 -8
@@ -10,7 +10,6 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
10
10
  var _react = require("react");
11
11
  var _react2 = require("@emotion/react");
12
12
  var _bindEventListener = require("bind-event-listener");
13
- var _reactIntlNext = require("react-intl-next");
14
13
  var _analytics = require("@atlaskit/editor-common/analytics");
15
14
  var _hooks = require("@atlaskit/editor-common/hooks");
16
15
  var _keymaps = require("@atlaskit/editor-common/keymaps");
@@ -69,14 +68,14 @@ var selectedStyles = (0, _react2.css)({
69
68
  backgroundColor: "var(--ds-background-selected, #E9F2FF)",
70
69
  color: "var(--ds-icon-selected, #0C66E4)"
71
70
  });
72
- var DragHandleInternal = function DragHandleInternal(_ref) {
71
+ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
73
72
  var _api$core2, _api$analytics2, _api$core4, _api$core6;
74
73
  var view = _ref.view,
75
74
  api = _ref.api,
75
+ formatMessage = _ref.formatMessage,
76
76
  getPos = _ref.getPos,
77
77
  anchorName = _ref.anchorName,
78
78
  nodeType = _ref.nodeType,
79
- formatMessage = _ref.intl.formatMessage,
80
79
  handleOptions = _ref.handleOptions,
81
80
  _ref$isTopLevelNode = _ref.isTopLevelNode,
82
81
  isTopLevelNode = _ref$isTopLevelNode === void 0 ? true : _ref$isTopLevelNode;
@@ -377,7 +376,7 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
377
376
  keymap: _keymaps.dragToMoveDown
378
377
  }];
379
378
  var isParentNodeOfTypeLayout;
380
- if (!isTopLevelNode && handleOptions !== null && handleOptions !== void 0 && handleOptions.isFocused && (0, _platformFeatureFlags.fg)('platform_editor_element_dnd_nested_a11y')) {
379
+ if (!isTopLevelNode && handleOptions !== null && handleOptions !== void 0 && handleOptions.isFocused && (0, _experiments.editorExperiment)('nested-dnd', true) && (0, _platformFeatureFlags.fg)('platform_editor_element_dnd_nested_a11y')) {
381
380
  isParentNodeOfTypeLayout = nodeType === 'layoutSection' || view.state.doc.resolve((0, _utils.getNestedNodePosition)(view.state)).node().type.name === 'layoutColumn';
382
381
  if (isParentNodeOfTypeLayout) {
383
382
  helpDescriptors = [].concat((0, _toConsumableArray2.default)(helpDescriptors), [{
@@ -424,5 +423,4 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
424
423
  });
425
424
  }
426
425
  }, renderButton()) : renderButton();
427
- };
428
- var DragHandle = exports.DragHandle = (0, _reactIntlNext.injectIntl)(DragHandleInternal);
426
+ };
@@ -62,15 +62,28 @@ var nestedDropZoneStyle = (0, _react2.css)({
62
62
  width: 'unset'
63
63
  });
64
64
  var enableDropZone = ['paragraph', 'mediaSingle', 'heading', 'codeBlock', 'decisionList', 'bulletList', 'orderedList', 'taskList', 'extension', 'blockCard'];
65
+ var fullHeightStyle = (0, _react2.css)({
66
+ top: '4px',
67
+ bottom: '4px',
68
+ height: 'unset',
69
+ zIndex: 10
70
+ });
71
+
72
+ // This z index is used in container like layout
73
+ var fullHeightStyleAdjustZIndexStyle = (0, _react2.css)({
74
+ zIndex: 0
75
+ });
65
76
  var HoverZone = function HoverZone(_ref) {
66
77
  var onDragEnter = _ref.onDragEnter,
67
78
  onDragLeave = _ref.onDragLeave,
68
79
  onDrop = _ref.onDrop,
69
80
  node = _ref.node,
81
+ parent = _ref.parent,
70
82
  editorWidth = _ref.editorWidth,
71
83
  anchorHeightsCache = _ref.anchorHeightsCache,
72
84
  position = _ref.position,
73
- isNestedDropTarget = _ref.isNestedDropTarget;
85
+ isNestedDropTarget = _ref.isNestedDropTarget,
86
+ dropTargetStyle = _ref.dropTargetStyle;
74
87
  var ref = (0, _react.useRef)(null);
75
88
  (0, _react.useEffect)(function () {
76
89
  if (ref.current) {
@@ -97,14 +110,23 @@ var HoverZone = function HoverZone(_ref) {
97
110
  maxWidth: "".concat(editorWidth || 0, "px")
98
111
  });
99
112
  }, [anchorHeightsCache, editorWidth, node, position]);
113
+ var isFullHeight = (0, _react.useMemo)(function () {
114
+ return dropTargetStyle === 'fullHeight';
115
+ }, [dropTargetStyle]);
116
+ var isFullHeightInLayout = (0, _react.useMemo)(function () {
117
+ return isFullHeight && (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutColumn';
118
+ }, [isFullHeight, parent === null || parent === void 0 ? void 0 : parent.type.name]);
100
119
  return (0, _react2.jsx)("div", {
101
120
  ref: ref
102
121
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
103
122
  ,
104
- className: "drop-target-hover-zone-".concat(position)
123
+ className: "drop-target-hover-zone-".concat(position),
124
+ "data-testid": "drop-target-zone-".concat(position)
105
125
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
106
126
  ,
107
- css: [dropZoneStyles, isNestedDropTarget && nestedDropZoneStyle, hoverZoneUpperStyle]
127
+ css: [dropZoneStyles, isNestedDropTarget && nestedDropZoneStyle,
128
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
129
+ hoverZoneUpperStyle, isFullHeight && fullHeightStyle, isFullHeightInLayout && fullHeightStyleAdjustZIndexStyle]
108
130
  });
109
131
  };
110
132
  var DropTargetV2 = exports.DropTargetV2 = function DropTargetV2(_ref2) {
@@ -115,7 +137,8 @@ var DropTargetV2 = exports.DropTargetV2 = function DropTargetV2(_ref2) {
115
137
  nextNode = _ref2.nextNode,
116
138
  parentNode = _ref2.parentNode,
117
139
  formatMessage = _ref2.formatMessage,
118
- anchorHeightsCache = _ref2.anchorHeightsCache;
140
+ anchorHeightsCache = _ref2.anchorHeightsCache,
141
+ dropTargetStyle = _ref2.dropTargetStyle;
119
142
  var _useState = (0, _react.useState)(false),
120
143
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
121
144
  isDraggedOver = _useState2[0],
@@ -137,10 +160,11 @@ var DropTargetV2 = exports.DropTargetV2 = function DropTargetV2(_ref2) {
137
160
  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, undefined, formatMessage));
138
161
  }
139
162
  };
163
+ var isFullHeight = dropTargetStyle === 'fullHeight';
140
164
  var dynamicStyle = (_dynamicStyle = {
141
165
  width: isNestedDropTarget ? 'unset' : '100%'
142
166
  }, (0, _defineProperty2.default)(_dynamicStyle, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, isNestedDropTarget ? '100%' : "".concat((widthState === null || widthState === void 0 ? void 0 : widthState.lineLength) || DEFAULT_DROP_INDICATOR_WIDTH, "px")), (0, _defineProperty2.default)(_dynamicStyle, EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, isNestedDropTarget ? (0, _consts.getNestedNodeLeftPaddingMargin)(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0'), (0, _defineProperty2.default)(_dynamicStyle, EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, (0, _experiments.editorExperiment)('nested-dnd', true) ? _constants.layers.navigation() : _constants.layers.card()), _dynamicStyle);
143
- return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(HoverZone, {
167
+ return (0, _react2.jsx)(_react.Fragment, null, !isFullHeight && (0, _react2.jsx)(HoverZone, {
144
168
  onDragEnter: function onDragEnter() {
145
169
  return setIsDraggedOver(true);
146
170
  },
@@ -176,9 +200,11 @@ var DropTargetV2 = exports.DropTargetV2 = function DropTargetV2(_ref2) {
176
200
  },
177
201
  onDrop: onDrop,
178
202
  node: nextNode,
203
+ parent: parentNode,
179
204
  editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
180
205
  anchorHeightsCache: anchorHeightsCache,
181
206
  position: "lower",
182
- isNestedDropTarget: isNestedDropTarget
207
+ isNestedDropTarget: isNestedDropTarget,
208
+ dropTargetStyle: dropTargetStyle
183
209
  }));
184
210
  };
@@ -120,6 +120,8 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref3) {
120
120
  return;
121
121
  }
122
122
 
123
+ // This should be moved to platform/packages/editor/editor-plugin-block-controls/src/utils/validation.ts
124
+ // Since we are moved to drop-target-v2
123
125
  // Place experiments here instead of just inside move-node.ts as it stops the drag marker from appearing.
124
126
  if ((0, _experiments.editorExperiment)('nest-media-and-codeblock-in-quote', false)) {
125
127
  var _api$blockControls;
@@ -128,18 +128,12 @@ var withFormatInLayoutStyleFixSelectors = ["".concat(dragHandleContainer, ":firs
128
128
  var withInlineNodeStyleWithChromeFix = (0, _react.css)((0, _defineProperty2.default)({}, withInlineNodeStyleWithChromeFixSelectors, {
129
129
  transform: 'scale(0)'
130
130
  }));
131
- var globalStyles = (0, _experiments.editorExperiment)('nested-dnd', true) ? (0, _react.css)({
131
+ var globalStyles = (0, _react.css)({
132
132
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
133
133
  '.ProseMirror-widget:first-child + *:not([data-panel-type], .code-block, [data-node-type="nestedExpand"])': {
134
134
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles -- Ignored via go/DSP-18766
135
135
  marginTop: '0 !important'
136
136
  }
137
- }) : (0, _react.css)({
138
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
139
- '.ProseMirror-widget:first-child + *': {
140
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles -- Ignored via go/DSP-18766
141
- marginTop: '0 !important'
142
- }
143
137
  });
144
138
  var withDividerInPanelStyleFix = (0, _react.css)((0, _defineProperty2.default)({}, "".concat(dividerBodiedInCustomPanelWithNoIconSelector), {
145
139
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isStepText = exports.isStepDelete = exports.getTrMetadata = void 0;
7
+ var _transform = require("@atlaskit/editor-prosemirror/transform");
8
+ /**
9
+ * Checks if step adds inline char
10
+ * @param s
11
+ * @returns True if step adds inline char
12
+ */
13
+ var isStepText = exports.isStepText = function isStepText(s) {
14
+ var content = s.slice.content.firstChild;
15
+ return s.from === s.to && s.slice.content.childCount === 1 && !!content && !!content.text;
16
+ };
17
+
18
+ /**
19
+ * Checks if step is an inline delete/backspace (replace range from -> from + 1 with empty content)
20
+ * @param s
21
+ * @returns True if delete/backspace
22
+ */
23
+ var isStepDelete = exports.isStepDelete = function isStepDelete(s) {
24
+ var content = s.slice.content;
25
+ return s.to === s.from + 1 && content.size === 0;
26
+ };
27
+
28
+ /**
29
+ * Get metadata from the transaction.
30
+ * @param tr
31
+ * @returns Min 'from', max 'to' (from + slice size). If no steps, returns pos range of entire doc.
32
+ * Number of ReplaceStep and ReplaceAroundStep steps 'numReplaceSteps'.
33
+ * 'isAllText' if all steps are represent adding inline text or a backspace/delete or no-op
34
+ */
35
+ var getTrMetadata = exports.getTrMetadata = function getTrMetadata(tr) {
36
+ var from;
37
+ var to;
38
+ var numReplaceSteps = 0;
39
+ var isAllText = true;
40
+ tr.steps.forEach(function (s) {
41
+ if (s instanceof _transform.ReplaceStep || s instanceof _transform.ReplaceAroundStep) {
42
+ if (s instanceof _transform.ReplaceAroundStep || s instanceof _transform.ReplaceStep && !isStepText(s) && !isStepDelete(s)) {
43
+ isAllText = false;
44
+ }
45
+ var $to = s.from + s.slice.size;
46
+ from = from === undefined || from > s.from ? s.from : from;
47
+ to = to === undefined || to < $to ? $to : to;
48
+ numReplaceSteps++;
49
+ }
50
+ });
51
+ if (from === undefined) {
52
+ from = 0;
53
+ }
54
+ if (to === undefined || to > tr.doc.nodeSize - 2) {
55
+ to = tr.doc.nodeSize - 2;
56
+ }
57
+ return {
58
+ from: from,
59
+ to: to,
60
+ numReplaceSteps: numReplaceSteps,
61
+ isAllText: isAllText
62
+ };
63
+ };
@@ -8,6 +8,7 @@ exports.canMoveNodeToIndex = canMoveNodeToIndex;
8
8
  exports.transformSliceExpandToNestedExpand = exports.transformExpandToNestedExpand = exports.memoizedTransformExpandToNestedExpand = exports.isNestedExpand = exports.isLayoutColumn = exports.isInsideTable = exports.isExpand = exports.isDoc = void 0;
9
9
  var _memoizeOne = _interopRequireDefault(require("memoize-one"));
10
10
  var _model = require("@atlaskit/editor-prosemirror/model");
11
+ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
11
12
  var isInsideTable = exports.isInsideTable = function isInsideTable(nodeType) {
12
13
  var _nodeType$schema$node = nodeType.schema.nodes,
13
14
  tableCell = _nodeType$schema$node.tableCell,
@@ -70,6 +71,22 @@ var memoizedTransformExpandToNestedExpand = exports.memoizedTransformExpandToNes
70
71
  });
71
72
  function canMoveNodeToIndex(destParent, indexIntoParent, srcNode) {
72
73
  var srcNodeType = srcNode.type;
74
+ var parentNodeType = destParent === null || destParent === void 0 ? void 0 : destParent.type.name;
75
+ var activeNodeType = srcNode === null || srcNode === void 0 ? void 0 : srcNode.type.name;
76
+
77
+ // Place experiments here instead of just inside move-node.ts as it stops the drag marker from appearing.
78
+ if ((0, _experiments.editorExperiment)('nest-media-and-codeblock-in-quote', false)) {
79
+ if (parentNodeType === 'blockquote' && (activeNodeType === 'mediaGroup' || activeNodeType === 'mediaSingle' || activeNodeType === 'codeBlock')) {
80
+ return false;
81
+ }
82
+ }
83
+
84
+ // Place experiments here instead of just inside move-node.ts as it stops the drag marker from appearing.
85
+ if ((0, _experiments.editorExperiment)('nested-expand-in-expand', false)) {
86
+ if (parentNodeType === 'expand' && (activeNodeType === 'expand' || activeNodeType === 'nestedExpand')) {
87
+ return false;
88
+ }
89
+ }
73
90
  if (isInsideTable(destParent.type) && isExpand(srcNodeType)) {
74
91
  if (memoizedTransformExpandToNestedExpand(srcNode)) {
75
92
  srcNodeType = srcNodeType.schema.nodes.nestedExpand;
@@ -65,7 +65,7 @@ const getCurrentNodePos = (state, isParentNodeOfTypeLayout) => {
65
65
  // 2. caret cursor is inside the node
66
66
  // 3. the start of the selection is inside the node
67
67
  currentNodePos = selection.$from.before(1);
68
- if (selection.$from.depth > 0 && fg('platform_editor_element_dnd_nested_a11y')) {
68
+ if (selection.$from.depth > 0 && editorExperiment('nested-dnd', true) && fg('platform_editor_element_dnd_nested_a11y')) {
69
69
  currentNodePos = getNestedNodePosition(state);
70
70
  }
71
71
  }
@@ -74,7 +74,8 @@ const getCurrentNodePos = (state, isParentNodeOfTypeLayout) => {
74
74
  export const moveNodeViaShortcut = (api, direction, formatMessage) => {
75
75
  return state => {
76
76
  let isParentNodeOfTypeLayout;
77
- if (fg('platform_editor_element_dnd_nested_a11y')) {
77
+ const shouldEnableNestedDndA11y = editorExperiment('nested-dnd', true) && fg('platform_editor_element_dnd_nested_a11y');
78
+ if (shouldEnableNestedDndA11y) {
78
79
  isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
79
80
  }
80
81
  const currentNodePos = getCurrentNodePos(state, isParentNodeOfTypeLayout);
@@ -83,7 +84,7 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
83
84
  const $pos = state.doc.resolve(currentNodePos);
84
85
  let moveToPos = -1;
85
86
  const nodeIndex = $pos.index();
86
- if (direction === DIRECTION.LEFT && fg('platform_editor_element_dnd_nested_a11y')) {
87
+ if (direction === DIRECTION.LEFT && shouldEnableNestedDndA11y) {
87
88
  if ($pos.depth < 2 || !isParentNodeOfTypeLayout) {
88
89
  return false;
89
90
  }
@@ -93,13 +94,13 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
93
94
  const grandParent = $pos.node($pos.depth - 1);
94
95
  const previousNode = grandParent ? grandParent.maybeChild(index - 1) : null;
95
96
  moveToPos = $pos.start() - ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.nodeSize) || 1);
96
- } else if (direction === DIRECTION.RIGHT && fg('platform_editor_element_dnd_nested_a11y')) {
97
+ } else if (direction === DIRECTION.RIGHT && shouldEnableNestedDndA11y) {
97
98
  if ($pos.depth < 2 || !isParentNodeOfTypeLayout) {
98
99
  return false;
99
100
  }
100
101
  moveToPos = $pos.after($pos.depth) + 1;
101
102
  } else if (direction === DIRECTION.UP) {
102
- const nodeBefore = $pos.depth > 1 && nodeIndex === 0 && fg('platform_editor_element_dnd_nested_a11y') ? $pos.node($pos.depth) : $pos.nodeBefore;
103
+ const nodeBefore = $pos.depth > 1 && nodeIndex === 0 && shouldEnableNestedDndA11y ? $pos.node($pos.depth) : $pos.nodeBefore;
103
104
  if (nodeBefore) {
104
105
  moveToPos = currentNodePos - nodeBefore.nodeSize;
105
106
  }
@@ -115,7 +116,7 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
115
116
  const nodeType = (_state$doc$nodeAt = state.doc.nodeAt(currentNodePos)) === null || _state$doc$nodeAt === void 0 ? void 0 : _state$doc$nodeAt.type.name;
116
117
 
117
118
  // only move the node if the destination is at the same depth, not support moving a nested node to a parent node
118
- const shouldMoveNode = fg('platform_editor_element_dnd_nested_a11y') ? moveToPos > -1 && $pos.depth === state.doc.resolve(moveToPos).depth : moveToPos > -1;
119
+ const shouldMoveNode = shouldEnableNestedDndA11y ? moveToPos > -1 && $pos.depth === state.doc.resolve(moveToPos).depth : moveToPos > -1;
119
120
  if (shouldMoveNode) {
120
121
  var _api$core;
121
122
  api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
@@ -1,5 +1,6 @@
1
1
  import { isInTable } from '@atlaskit/editor-tables/utils';
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
3
4
  import { key } from '../pm-plugins/main';
4
5
  import { getNestedNodePosition } from '../utils';
5
6
  export const showDragHandleAtSelection = (api, shouldFocusParentNode) => (state, _, view) => {
@@ -7,7 +8,7 @@ export const showDragHandleAtSelection = (api, shouldFocusParentNode) => (state,
7
8
  $from
8
9
  } = state.selection;
9
10
  let shouldFocusParentNode;
10
- if ($from.depth > 1 && fg('platform_editor_element_dnd_nested_a11y')) {
11
+ if ($from.depth > 1 && editorExperiment('nested-dnd', true) && fg('platform_editor_element_dnd_nested_a11y')) {
11
12
  var _activeNode$handleOpt, _view$domAtPos;
12
13
  const {
13
14
  activeNode
@@ -2,7 +2,6 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { createElement } from 'react';
3
3
  import { bind } from 'bind-event-listener';
4
4
  import ReactDOM from 'react-dom';
5
- import { RawIntlProvider } from 'react-intl-next';
6
5
  import uuid from 'uuid';
7
6
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
8
7
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
@@ -18,6 +17,9 @@ const IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn', 'l
18
17
  const IGNORE_NODE_DESCENDANTS = ['listItem', 'taskList', 'decisionList', 'mediaSingle'];
19
18
  const PARENT_WITH_END_DROP_TARGET = ['tableCell', 'tableHeader', 'panel', 'layoutColumn', 'expand', 'nestedExpand', 'bodiedExtension'];
20
19
  const DISABLE_CHILD_DROP_TARGET = ['orderedList', 'bulletList'];
20
+ export const TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
21
+ export const TYPE_HANDLE_DEC = 'drag-handle';
22
+ export const TYPE_NODE_DEC = 'node-decoration';
21
23
  const getNestedDepth = () => editorExperiment('nested-dnd', true) ? 100 : 0;
22
24
  export const getNodeAnchor = node => {
23
25
  const handleId = ObjHash.getForNode(node);
@@ -66,6 +68,48 @@ const shouldDescend = node => {
66
68
  }
67
69
  return true;
68
70
  };
71
+
72
+ /**
73
+ * Find drop target decorations in the pos range between from and to
74
+ * @param decorations
75
+ * @param from
76
+ * @param to
77
+ * @returns
78
+ */
79
+ export const findDropTargetDecs = (decorations, from, to) => {
80
+ return decorations.find(from, to, spec => spec.type === TYPE_DROP_TARGET_DEC);
81
+ };
82
+ export const findHandleDec = (decorations, from, to) => {
83
+ return decorations.find(from, to, spec => spec.type === TYPE_HANDLE_DEC);
84
+ };
85
+
86
+ /**
87
+ * Find node decorations in the pos range between from and to (non-inclusive)
88
+ * @param decorations
89
+ * @param from
90
+ * @param to
91
+ * @returns
92
+ */
93
+ export const findNodeDecs = (decorations, from, to) => {
94
+ let newfrom = from;
95
+ let newTo = to;
96
+
97
+ // make it non-inclusive
98
+ if (newfrom !== undefined) {
99
+ newfrom++;
100
+ }
101
+
102
+ // make it non-inclusive
103
+ if (newTo !== undefined) {
104
+ newTo--;
105
+ }
106
+
107
+ // return empty array if range reversed
108
+ if (newfrom !== undefined && newTo !== undefined && newfrom > newTo) {
109
+ return new Array();
110
+ }
111
+ return decorations.find(newfrom, newTo, spec => spec.type === TYPE_NODE_DEC);
112
+ };
69
113
  export const createDropTargetDecoration = (pos, props, side, anchorHeightsCache) => {
70
114
  return Decoration.widget(pos, (_, getPos) => {
71
115
  const element = document.createElement('div');
@@ -93,13 +137,16 @@ export const createDropTargetDecoration = (pos, props, side, anchorHeightsCache)
93
137
  }
94
138
  return element;
95
139
  }, {
96
- type: 'drop-target-decoration',
140
+ type: TYPE_DROP_TARGET_DEC,
97
141
  side
98
142
  });
99
143
  };
100
- export const dropTargetDecorations = (newState, api, formatMessage, activeNode, anchorHeightsCache) => {
101
- const decs = [];
144
+ export const dropTargetDecorations = (newState, api, formatMessage, activeNode, anchorHeightsCache, from, to) => {
102
145
  unmountDecorations('data-blocks-drop-target-container');
146
+ const decs = [];
147
+ const POS_END_OF_DOC = newState.doc.nodeSize - 2;
148
+ const docFrom = from === undefined || from < 0 ? 0 : from;
149
+ const docTo = to === undefined || to > POS_END_OF_DOC ? POS_END_OF_DOC : to;
103
150
  let prevNode;
104
151
  const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
105
152
  const activePMNode = typeof activeNodePos === 'number' && newState.doc.resolve(activeNodePos).nodeAfter;
@@ -117,7 +164,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
117
164
  popNodeStack(depth);
118
165
  prevNodeStack.push(node);
119
166
  };
120
- newState.doc.descendants((node, pos, parent, index) => {
167
+ newState.doc.nodesBetween(docFrom, docTo, (node, pos, parent, index) => {
121
168
  let depth = 0;
122
169
  // drop target deco at the end position
123
170
  let endPos;
@@ -155,19 +202,27 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
155
202
  }
156
203
  }
157
204
  const previousNode = fg('platform_editor_drag_and_drop_target_v2') ? popNodeStack(depth) : prevNode; // created scoped variable
205
+
206
+ // only table and layout need to render full height drop target
207
+ const isInSupportedContainer = fg('platform_editor_drag_and_drop_target_v2') && ['tableCell', 'tableHeader', 'layoutColumn'].includes((parent === null || parent === void 0 ? void 0 : parent.type.name) || '');
208
+
209
+ // container with only an empty paragrah
210
+ const shouldShowFullHeight = isInSupportedContainer && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node && (parent === null || parent === void 0 ? void 0 : parent.childCount) === 1 && isEmptyParagraph(node) && fg('platform_editor_drag_and_drop_target_v2');
158
211
  decs.push(createDropTargetDecoration(pos, {
159
212
  api,
160
213
  prevNode: previousNode,
161
214
  nextNode: node,
162
215
  parentNode: parent || undefined,
163
- formatMessage
216
+ formatMessage,
217
+ dropTargetStyle: shouldShowFullHeight ? 'fullHeight' : 'default'
164
218
  }, -1, anchorHeightsCache));
165
219
  if (endPos !== undefined) {
166
220
  decs.push(createDropTargetDecoration(endPos, {
167
221
  api,
168
222
  prevNode: fg('platform_editor_drag_and_drop_target_v2') ? node : undefined,
169
223
  parentNode: parent || undefined,
170
- formatMessage
224
+ formatMessage,
225
+ dropTargetStyle: isInSupportedContainer ? 'fullHeight' : 'default'
171
226
  }, -1, anchorHeightsCache));
172
227
  }
173
228
  if (fg('platform_editor_drag_and_drop_target_v2')) {
@@ -177,12 +232,14 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
177
232
  }
178
233
  return depth < getNestedDepth() && shouldDescend(node);
179
234
  });
180
- decs.push(createDropTargetDecoration(newState.doc.nodeSize - 2, {
181
- api,
182
- formatMessage,
183
- prevNode: newState.doc.lastChild || undefined,
184
- parentNode: newState.doc
185
- }, undefined, anchorHeightsCache));
235
+ if (docTo === POS_END_OF_DOC) {
236
+ decs.push(createDropTargetDecoration(POS_END_OF_DOC, {
237
+ api,
238
+ formatMessage,
239
+ prevNode: newState.doc.lastChild || undefined,
240
+ parentNode: newState.doc
241
+ }, undefined, anchorHeightsCache));
242
+ }
186
243
  return decs;
187
244
  };
188
245
  export const emptyParagraphNodeDecorations = () => {
@@ -192,7 +249,7 @@ export const emptyParagraphNodeDecorations = () => {
192
249
  style,
193
250
  ['data-drag-handler-anchor-name']: anchorName
194
251
  }, {
195
- type: 'node-decoration'
252
+ type: TYPE_NODE_DEC
196
253
  });
197
254
  };
198
255
  class ObjHash {
@@ -214,18 +271,16 @@ const shouldIgnoreNode = node => {
214
271
  }
215
272
  return IGNORE_NODES.includes(node.type.name);
216
273
  };
217
- export const nodeDecorations = newState => {
274
+ export const nodeDecorations = (newState, from, to) => {
218
275
  const decs = [];
219
- newState.doc.descendants((node, pos, _parent, index) => {
276
+ const docFrom = from === undefined || from < 0 ? 0 : from;
277
+ const docTo = to === undefined || to > newState.doc.nodeSize - 2 ? newState.doc.nodeSize - 2 : to;
278
+ newState.doc.nodesBetween(docFrom, docTo, (node, pos, _parent, index) => {
220
279
  let depth = 0;
221
280
  let anchorName;
222
281
  const shouldDescend = !IGNORE_NODE_DESCENDANTS.includes(node.type.name);
223
- if (editorExperiment('dnd-input-performance-optimisation', true, {
224
- exposure: true
225
- }) || editorExperiment('nested-dnd', true)) {
226
- const handleId = ObjHash.getForNode(node);
227
- anchorName = `--node-anchor-${node.type.name}-${handleId}`;
228
- }
282
+ const handleId = ObjHash.getForNode(node);
283
+ anchorName = `--node-anchor-${node.type.name}-${handleId}`;
229
284
  if (editorExperiment('nested-dnd', true)) {
230
285
  var _anchorName;
231
286
  // Doesn't descend into a node
@@ -247,7 +302,7 @@ export const nodeDecorations = newState => {
247
302
  ['data-drag-handler-node-type']: node.type.name,
248
303
  ['data-drag-handler-anchor-depth']: `${depth}`
249
304
  }, {
250
- type: 'node-decoration',
305
+ type: TYPE_NODE_DEC,
251
306
  anchorName,
252
307
  nodeType: node.type.name
253
308
  }));
@@ -255,7 +310,8 @@ export const nodeDecorations = newState => {
255
310
  });
256
311
  return decs;
257
312
  };
258
- export const dragHandleDecoration = (api, getIntl, pos, anchorName, nodeType, handleOptions) => {
313
+ export const dragHandleDecoration = (api, formatMessage, pos, anchorName, nodeType, handleOptions) => {
314
+ unmountDecorations('data-blocks-drag-handle-container');
259
315
  let unbind;
260
316
  return Decoration.widget(pos, (view, getPos) => {
261
317
  const element = document.createElement('span');
@@ -269,7 +325,7 @@ export const dragHandleDecoration = (api, getIntl, pos, anchorName, nodeType, ha
269
325
  isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
270
326
  /*
271
327
  * We disable mouseover event to fix flickering issue on hover
272
- * However, the tooltip for nested drag handle is not long working.
328
+ * However, the tooltip for nested drag handle is no long working.
273
329
  */
274
330
  if (!isTopLevelNode) {
275
331
  // This will also hide the tooltip.
@@ -281,26 +337,25 @@ export const dragHandleDecoration = (api, getIntl, pos, anchorName, nodeType, ha
281
337
  });
282
338
  }
283
339
  }
284
- unmountDecorations('data-blocks-drag-handle-container');
285
340
 
286
341
  // There are times when global clear: "both" styles are applied to this decoration causing jumpiness
287
342
  // due to margins applied to other nodes eg. Headings
288
343
  element.style.clear = 'unset';
289
- ReactDOM.render( /*#__PURE__*/createElement(RawIntlProvider, {
290
- value: getIntl()
291
- }, /*#__PURE__*/createElement(DragHandle, {
344
+ ReactDOM.render( /*#__PURE__*/createElement(DragHandle, {
292
345
  view,
293
346
  api,
347
+ formatMessage,
294
348
  getPos,
295
349
  anchorName,
296
350
  nodeType,
297
351
  handleOptions,
298
352
  isTopLevelNode
299
- })), element);
353
+ }), element);
300
354
  return element;
301
355
  }, {
302
356
  side: -1,
303
- id: 'drag-handle',
357
+ type: TYPE_HANDLE_DEC,
358
+ testid: `${TYPE_HANDLE_DEC}-${uuid()}`,
304
359
  destroy: () => {
305
360
  if (editorExperiment('nested-dnd', true)) {
306
361
  unbind && unbind();
@@ -1,6 +1,7 @@
1
1
  import { bindKeymapWithCommand, dragToMoveDown, dragToMoveLeft, dragToMoveRight, dragToMoveUp, showElementDragHandle } from '@atlaskit/editor-common/keymaps';
2
2
  import { keydownHandler } from '@atlaskit/editor-prosemirror/keymap';
3
3
  import { fg } from '@atlaskit/platform-feature-flags';
4
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
4
5
  import { moveNodeViaShortcut } from '../commands/move-node';
5
6
  import { showDragHandleAtSelection } from '../commands/show-drag-handle';
6
7
  import { DIRECTION } from '../consts';
@@ -14,8 +15,10 @@ function keymapList(api, formatMessage) {
14
15
  }, keymapList);
15
16
  bindKeymapWithCommand(dragToMoveUp.common, moveNodeViaShortcut(api, DIRECTION.UP, formatMessage), keymapList);
16
17
  bindKeymapWithCommand(dragToMoveDown.common, moveNodeViaShortcut(api, DIRECTION.DOWN, formatMessage), keymapList);
17
- fg('platform_editor_element_dnd_nested_a11y') && bindKeymapWithCommand(dragToMoveLeft.common, moveNodeViaShortcut(api, DIRECTION.LEFT, formatMessage), keymapList);
18
- fg('platform_editor_element_dnd_nested_a11y') && bindKeymapWithCommand(dragToMoveRight.common, moveNodeViaShortcut(api, DIRECTION.RIGHT, formatMessage), keymapList);
18
+ if (editorExperiment('nested-dnd', true) && fg('platform_editor_element_dnd_nested_a11y')) {
19
+ bindKeymapWithCommand(dragToMoveLeft.common, moveNodeViaShortcut(api, DIRECTION.LEFT, formatMessage), keymapList);
20
+ bindKeymapWithCommand(dragToMoveRight.common, moveNodeViaShortcut(api, DIRECTION.RIGHT, formatMessage), keymapList);
21
+ }
19
22
  }
20
23
  return keymapList;
21
24
  }