@atlaskit/editor-plugin-block-controls 2.6.2 → 2.7.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 (60) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/cjs/commands/move-to-layout.js +76 -0
  3. package/dist/cjs/consts.js +3 -2
  4. package/dist/cjs/plugin.js +3 -12
  5. package/dist/cjs/pm-plugins/decorations.js +15 -11
  6. package/dist/cjs/pm-plugins/handle-mouse-over.js +2 -12
  7. package/dist/cjs/pm-plugins/main.js +14 -18
  8. package/dist/cjs/ui/consts.js +8 -1
  9. package/dist/cjs/ui/drop-target-v2.js +24 -17
  10. package/dist/cjs/ui/inline-drop-target.js +138 -0
  11. package/dist/cjs/utils/advanced-layouts-flags.js +11 -0
  12. package/dist/cjs/utils/anchor-utils.js +71 -15
  13. package/dist/cjs/utils/inline-drop-target.js +18 -0
  14. package/dist/es2019/commands/move-to-layout.js +69 -0
  15. package/dist/es2019/consts.js +2 -1
  16. package/dist/es2019/plugin.js +2 -10
  17. package/dist/es2019/pm-plugins/decorations.js +15 -11
  18. package/dist/es2019/pm-plugins/handle-mouse-over.js +2 -12
  19. package/dist/es2019/pm-plugins/main.js +15 -21
  20. package/dist/es2019/ui/consts.js +7 -0
  21. package/dist/es2019/ui/drop-target-v2.js +24 -16
  22. package/dist/es2019/ui/inline-drop-target.js +130 -0
  23. package/dist/es2019/utils/advanced-layouts-flags.js +5 -0
  24. package/dist/es2019/utils/anchor-utils.js +55 -9
  25. package/dist/es2019/utils/inline-drop-target.js +12 -0
  26. package/dist/esm/commands/move-to-layout.js +70 -0
  27. package/dist/esm/consts.js +2 -1
  28. package/dist/esm/plugin.js +3 -12
  29. package/dist/esm/pm-plugins/decorations.js +15 -11
  30. package/dist/esm/pm-plugins/handle-mouse-over.js +2 -12
  31. package/dist/esm/pm-plugins/main.js +15 -19
  32. package/dist/esm/ui/consts.js +7 -0
  33. package/dist/esm/ui/drop-target-v2.js +24 -17
  34. package/dist/esm/ui/inline-drop-target.js +130 -0
  35. package/dist/esm/utils/advanced-layouts-flags.js +5 -0
  36. package/dist/esm/utils/anchor-utils.js +70 -14
  37. package/dist/esm/utils/inline-drop-target.js +12 -0
  38. package/dist/types/commands/move-to-layout.d.ts +3 -0
  39. package/dist/types/consts.d.ts +1 -0
  40. package/dist/types/pm-plugins/decorations.d.ts +3 -3
  41. package/dist/types/pm-plugins/main.d.ts +3 -4
  42. package/dist/types/types.d.ts +1 -1
  43. package/dist/types/ui/consts.d.ts +3 -0
  44. package/dist/types/ui/drop-target-v2.d.ts +3 -3
  45. package/dist/types/ui/inline-drop-target.d.ts +20 -0
  46. package/dist/types/utils/advanced-layouts-flags.d.ts +1 -0
  47. package/dist/types/utils/anchor-utils.d.ts +16 -3
  48. package/dist/types/utils/inline-drop-target.d.ts +2 -0
  49. package/dist/types-ts4.5/commands/move-to-layout.d.ts +3 -0
  50. package/dist/types-ts4.5/consts.d.ts +1 -0
  51. package/dist/types-ts4.5/pm-plugins/decorations.d.ts +3 -3
  52. package/dist/types-ts4.5/pm-plugins/main.d.ts +3 -4
  53. package/dist/types-ts4.5/types.d.ts +1 -1
  54. package/dist/types-ts4.5/ui/consts.d.ts +3 -0
  55. package/dist/types-ts4.5/ui/drop-target-v2.d.ts +3 -3
  56. package/dist/types-ts4.5/ui/inline-drop-target.d.ts +20 -0
  57. package/dist/types-ts4.5/utils/advanced-layouts-flags.d.ts +1 -0
  58. package/dist/types-ts4.5/utils/anchor-utils.d.ts +16 -3
  59. package/dist/types-ts4.5/utils/inline-drop-target.d.ts +2 -0
  60. package/package.json +8 -5
@@ -1,3 +1,4 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  /**
2
3
  * @jsxRuntime classic
3
4
  * @jsx jsx
@@ -14,7 +15,9 @@ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
14
15
  import { getNodeAnchor } from '../pm-plugins/decorations';
15
16
  import { isAnchorSupported } from '../utils/anchor-utils';
16
17
  import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
18
+ import { shouldAllowInlineDropTarget } from '../utils/inline-drop-target';
17
19
  import { getNestedNodeLeftPaddingMargin } from './consts';
20
+ import { InlineDropTarget } from './inline-drop-target';
18
21
  const DEFAULT_DROP_INDICATOR_WIDTH = 760;
19
22
  const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH = '--editor-block-controls-drop-indicator-width';
20
23
  const EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN = '--editor-block-controls-drop-target-leftMargin';
@@ -70,7 +73,7 @@ const HoverZone = ({
70
73
  node,
71
74
  parent,
72
75
  editorWidth,
73
- anchorHeightsCache,
76
+ anchorRectCache,
74
77
  position,
75
78
  isNestedDropTarget,
76
79
  dropTargetStyle
@@ -90,7 +93,7 @@ const HoverZone = ({
90
93
  const anchorName = node ? getNodeAnchor(node) : '';
91
94
  const heightStyleOffset = `var(--editor-block-controls-drop-indicator-gap, 0)/2`;
92
95
  const transformOffset = `var(${EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET}, 0)`;
93
- const heightStyle = anchorName && enableDropZone.includes((node === null || node === void 0 ? void 0 : node.type.name) || '') ? isAnchorSupported() ? `calc(anchor-size(${anchorName} height)/2 + ${heightStyleOffset})` : `calc(${((anchorHeightsCache === null || anchorHeightsCache === void 0 ? void 0 : anchorHeightsCache.getHeight(anchorName)) || 0) / 2}px + ${heightStyleOffset})` : '4px';
96
+ const heightStyle = anchorName && enableDropZone.includes((node === null || node === void 0 ? void 0 : node.type.name) || '') ? isAnchorSupported() ? `calc(anchor-size(${anchorName} height)/2 + ${heightStyleOffset})` : `calc(${((anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getHeight(anchorName)) || 0) / 2}px + ${heightStyleOffset})` : '4px';
94
97
  const transform = position === 'upper' ? `translateY(calc(-100% + ${transformOffset}))` : `translateY(${transformOffset})`;
95
98
  return css({
96
99
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
@@ -100,7 +103,7 @@ const HoverZone = ({
100
103
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
101
104
  maxWidth: `${editorWidth || 0}px`
102
105
  });
103
- }, [anchorHeightsCache, editorWidth, node, position]);
106
+ }, [anchorRectCache, editorWidth, node, position]);
104
107
  const isFullHeight = useMemo(() => {
105
108
  return dropTargetStyle === 'fullHeight';
106
109
  }, [dropTargetStyle]);
@@ -120,16 +123,17 @@ const HoverZone = ({
120
123
  hoverZoneUpperStyle, isFullHeight && fullHeightStyle, isFullHeightInLayout && fullHeightStyleAdjustZIndexStyle]
121
124
  });
122
125
  };
123
- export const DropTargetV2 = ({
124
- api,
125
- getPos,
126
- prevNode,
127
- nextNode,
128
- parentNode,
129
- formatMessage,
130
- anchorHeightsCache,
131
- dropTargetStyle
132
- }) => {
126
+ export const DropTargetV2 = props => {
127
+ const {
128
+ api,
129
+ getPos,
130
+ prevNode,
131
+ nextNode,
132
+ parentNode,
133
+ formatMessage,
134
+ anchorRectCache,
135
+ dropTargetStyle
136
+ } = props;
133
137
  const [isDraggedOver, setIsDraggedOver] = useState(false);
134
138
  const {
135
139
  widthState
@@ -165,7 +169,7 @@ export const DropTargetV2 = ({
165
169
  onDrop: onDrop,
166
170
  node: prevNode,
167
171
  editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
168
- anchorHeightsCache: anchorHeightsCache,
172
+ anchorRectCache: anchorRectCache,
169
173
  position: "upper",
170
174
  isNestedDropTarget: isNestedDropTarget
171
175
  }), jsx("div", {
@@ -189,9 +193,13 @@ export const DropTargetV2 = ({
189
193
  node: nextNode,
190
194
  parent: parentNode,
191
195
  editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
192
- anchorHeightsCache: anchorHeightsCache,
196
+ anchorRectCache: anchorRectCache,
193
197
  position: "lower",
194
198
  isNestedDropTarget: isNestedDropTarget,
195
199
  dropTargetStyle: dropTargetStyle
196
- }));
200
+ }), shouldAllowInlineDropTarget(isNestedDropTarget, nextNode) && jsx(Fragment, null, jsx(InlineDropTarget, _extends({}, props, {
201
+ position: "left"
202
+ })), jsx(InlineDropTarget, _extends({}, props, {
203
+ position: "right"
204
+ }))));
197
205
  };
@@ -0,0 +1,130 @@
1
+ /* eslint-disable @atlaskit/design-system/consistent-css-prop-usage */
2
+ /* eslint-disable @atlaskit/ui-styling-standard/no-unsafe-values */
3
+ /**
4
+ * @jsxRuntime classic
5
+ * @jsx jsx
6
+ */
7
+ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
+
9
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
10
+ import { css, jsx } from '@emotion/react';
11
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
12
+ import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
13
+ import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
14
+ import { getNodeAnchor } from '../pm-plugins/decorations';
15
+ import { isAnchorSupported } from '../utils/anchor-utils';
16
+ const dropTargetCommonStyle = css({
17
+ position: 'absolute',
18
+ display: 'block'
19
+ });
20
+ const hideDropTargetStyle = css({
21
+ display: 'none'
22
+ });
23
+ const hoverZoneCommonStyle = css({
24
+ position: 'absolute',
25
+ // same value as block hover zone
26
+ zIndex: 110
27
+ });
28
+
29
+ // gap between node boundary and drop indicator/drop zone
30
+ const GAP = 4;
31
+ const HOVER_ZONE_WIDTH_OFFSET = 40;
32
+ const HOVER_ZONE_HEIGHT_OFFSET = 10;
33
+ const HOVER_ZONE_DEFAULT_WIDTH = 40;
34
+ export const InlineDropTarget = ({
35
+ api,
36
+ nextNode,
37
+ position,
38
+ anchorRectCache
39
+ }) => {
40
+ const {
41
+ widthState
42
+ } = useSharedPluginState(api, ['width']);
43
+ const [isDraggedOver, setIsDraggedOver] = useState(false);
44
+ const anchorName = nextNode ? getNodeAnchor(nextNode) : '';
45
+ const handleDragEnter = useCallback(() => {
46
+ setIsDraggedOver(true);
47
+ }, []);
48
+ const handleDragLeave = useCallback(() => {
49
+ setIsDraggedOver(false);
50
+ }, []);
51
+ const dropTargetRectStyle = useMemo(() => {
52
+ if (isAnchorSupported()) {
53
+ return css({
54
+ height: `calc(anchor-size(${anchorName} height))`,
55
+ positionAnchor: anchorName,
56
+ left: position === 'left' ? `calc(anchor(left) - ${GAP}px)` : `calc(anchor(right) + ${GAP}px)`,
57
+ top: `calc(anchor(top))`
58
+ });
59
+ }
60
+ const nodeRect = anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getRect(anchorName);
61
+ return css({
62
+ height: `calc(${(nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.height) || 0}px)`,
63
+ left: position === 'left' ? `${((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.left) || 0) - GAP}px` : `${((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.right) || 0) + GAP}px`,
64
+ top: `${(nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.top) || 0}px`
65
+ });
66
+ }, [anchorName, anchorRectCache, position]);
67
+ return jsx(Fragment, null, jsx("div", {
68
+ "data-test-id": `block-ctrl-drop-target-${position}`,
69
+ css: [dropTargetCommonStyle, dropTargetRectStyle, !isDraggedOver && hideDropTargetStyle]
70
+ }, jsx(DropIndicator, {
71
+ edge: position
72
+ })), jsx(InlineHoverZone, {
73
+ position: position,
74
+ node: nextNode,
75
+ editorWidthState: widthState,
76
+ anchorRectCache: anchorRectCache,
77
+ onDragEnter: handleDragEnter,
78
+ onDragLeave: handleDragLeave,
79
+ onDrop: () => {}
80
+ }));
81
+ };
82
+ export const InlineHoverZone = ({
83
+ node,
84
+ editorWidthState,
85
+ anchorRectCache,
86
+ position,
87
+ onDragEnter,
88
+ onDragLeave,
89
+ onDrop
90
+ }) => {
91
+ const ref = useRef(null);
92
+ const {
93
+ width: editorWith
94
+ } = editorWidthState || {};
95
+ const anchorName = node ? getNodeAnchor(node) : '';
96
+ useEffect(() => {
97
+ if (ref.current) {
98
+ return dropTargetForElements({
99
+ element: ref.current,
100
+ onDragEnter,
101
+ onDragLeave,
102
+ onDrop
103
+ });
104
+ }
105
+ }, [onDragEnter, onDragLeave, onDrop]);
106
+ const inlineHoverZoneRectStyle = useMemo(() => {
107
+ if (isAnchorSupported()) {
108
+ return css({
109
+ positionAnchor: anchorName,
110
+ left: position === 'left' ? 'unset' : `calc(anchor(right) + ${GAP}px)`,
111
+ right: position === 'left' ? `calc(anchor(left) + ${GAP}px)` : 'unset',
112
+ top: `calc(anchor(top))`,
113
+ width: editorWith ? `calc((${editorWith}px - anchor-size(${anchorName} width))/2 - ${HOVER_ZONE_WIDTH_OFFSET}px)` : `${HOVER_ZONE_DEFAULT_WIDTH}px`,
114
+ height: `calc(anchor-size(${anchorName} height))`
115
+ });
116
+ }
117
+ const nodeRect = anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getRect(anchorName);
118
+ const width = editorWith ? (editorWith - ((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.width) || 0)) / 2 - HOVER_ZONE_WIDTH_OFFSET : HOVER_ZONE_DEFAULT_WIDTH;
119
+ return css({
120
+ left: position === 'left' ? `${((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.left) || 0) - width - GAP}px` : `${((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.right) || 0) + GAP}px`,
121
+ top: `${(nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.top) || 0}px`,
122
+ width: `${width}px`,
123
+ height: `calc(${(anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getHeight(anchorName)) || 0}px - ${HOVER_ZONE_HEIGHT_OFFSET}px)`
124
+ });
125
+ }, [anchorName, anchorRectCache, editorWith, position]);
126
+ return jsx("div", {
127
+ ref: ref,
128
+ css: [hoverZoneCommonStyle, inlineHoverZoneRectStyle]
129
+ });
130
+ };
@@ -0,0 +1,5 @@
1
+ import { fg } from '@atlaskit/platform-feature-flags';
2
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
3
+ export const isPreRelease1 = () => {
4
+ return editorExperiment('advanced_layouts', true) || fg('platform_editor_advanced_layouts_pre_release_1');
5
+ };
@@ -7,34 +7,40 @@ export const isAnchorSupported = memoizeOne(() => {
7
7
  }
8
8
  return false;
9
9
  });
10
- export class AnchorHeightsCache {
10
+ export class AnchorRectCache {
11
11
  constructor() {
12
- _defineProperty(this, "anchorHeightsMap", {});
12
+ _defineProperty(this, "anchorRectMap", {});
13
13
  _defineProperty(this, "isAnchorSupported", isAnchorSupported());
14
14
  _defineProperty(this, "isDirty", true);
15
15
  _defineProperty(this, "view", null);
16
16
  }
17
17
  clear() {
18
18
  this.isDirty = true;
19
- this.anchorHeightsMap = {};
19
+ this.anchorRectMap = {};
20
20
  }
21
- getHeights() {
21
+ getRects() {
22
22
  if (this.isDirty) {
23
23
  var _this$view;
24
24
  const anchorElements = ((_this$view = this.view) === null || _this$view === void 0 ? void 0 : _this$view.dom.querySelectorAll('[data-drag-handler-anchor-name]')) || [];
25
- this.anchorHeightsMap = Array.from(anchorElements).reduce((prev, curr) => {
25
+ this.anchorRectMap = Array.from(anchorElements).reduce((prev, curr) => {
26
26
  const anchorName = curr.getAttribute('data-drag-handler-anchor-name');
27
27
  if (anchorName) {
28
28
  return {
29
29
  ...prev,
30
- [anchorName]: curr.clientHeight
30
+ [anchorName]: {
31
+ height: curr.clientHeight,
32
+ top: curr.offsetTop,
33
+ left: curr.offsetLeft,
34
+ right: curr.offsetLeft + curr.clientWidth,
35
+ width: curr.clientWidth
36
+ }
31
37
  };
32
38
  }
33
39
  return prev;
34
40
  }, {});
35
41
  this.isDirty = false;
36
42
  }
37
- return this.anchorHeightsMap;
43
+ return this.anchorRectMap;
38
44
  }
39
45
  setEditorView(view) {
40
46
  if (this.view !== view) {
@@ -42,10 +48,50 @@ export class AnchorHeightsCache {
42
48
  }
43
49
  }
44
50
  getHeight(anchorName) {
51
+ var _rects$anchorName;
45
52
  if (this.isAnchorSupported) {
46
53
  return null;
47
54
  }
48
- const heights = this.getHeights();
49
- return heights[anchorName];
55
+ const rects = this.getRects();
56
+ return (_rects$anchorName = rects[anchorName]) === null || _rects$anchorName === void 0 ? void 0 : _rects$anchorName.height;
57
+ }
58
+ getWidth(anchorName) {
59
+ var _rects$anchorName2;
60
+ if (this.isAnchorSupported) {
61
+ return null;
62
+ }
63
+ const rects = this.getRects();
64
+ return (_rects$anchorName2 = rects[anchorName]) === null || _rects$anchorName2 === void 0 ? void 0 : _rects$anchorName2.width;
65
+ }
66
+ getLeft(anchorName) {
67
+ var _rects$anchorName3;
68
+ if (this.isAnchorSupported) {
69
+ return null;
70
+ }
71
+ const rects = this.getRects();
72
+ return (_rects$anchorName3 = rects[anchorName]) === null || _rects$anchorName3 === void 0 ? void 0 : _rects$anchorName3.left;
73
+ }
74
+ getTop(anchorName) {
75
+ var _rects$anchorName4;
76
+ if (this.isAnchorSupported) {
77
+ return null;
78
+ }
79
+ const rects = this.getRects();
80
+ return (_rects$anchorName4 = rects[anchorName]) === null || _rects$anchorName4 === void 0 ? void 0 : _rects$anchorName4.top;
81
+ }
82
+ getRight(anchorName) {
83
+ var _rects$anchorName5;
84
+ if (this.isAnchorSupported) {
85
+ return null;
86
+ }
87
+ const rects = this.getRects();
88
+ return (_rects$anchorName5 = rects[anchorName]) === null || _rects$anchorName5 === void 0 ? void 0 : _rects$anchorName5.right;
89
+ }
90
+ getRect(anchorName) {
91
+ if (this.isAnchorSupported) {
92
+ return null;
93
+ }
94
+ const rects = this.getRects();
95
+ return rects[anchorName];
50
96
  }
51
97
  }
@@ -0,0 +1,12 @@
1
+ import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
2
+ import { MAX_LAYOUT_COLUMN_SUPPORTED } from '../consts';
3
+ import { isPreRelease1 } from './advanced-layouts-flags';
4
+ export const shouldAllowInlineDropTarget = (isNested, node) => {
5
+ if (!isPreRelease1() || isNested) {
6
+ return false;
7
+ }
8
+ if ((node === null || node === void 0 ? void 0 : node.type.name) === 'layoutSection') {
9
+ return node.childCount < MAX_LAYOUT_COLUMN_SUPPORTED;
10
+ }
11
+ return !isEmptyParagraph(node);
12
+ };
@@ -0,0 +1,70 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
+ import { DEFAULT_COLUMN_DISTRIBUTIONS } from '../ui/consts';
3
+ var createNewLayout = function createNewLayout(schema, layoutContents) {
4
+ // TODO update with constant
5
+ if (layoutContents.length === 0 || layoutContents.length > 5) {
6
+ return null;
7
+ }
8
+ var width = DEFAULT_COLUMN_DISTRIBUTIONS[layoutContents.length];
9
+ if (!width) {
10
+ return null;
11
+ }
12
+ var _ref = schema.nodes || {},
13
+ layoutSection = _ref.layoutSection,
14
+ layoutColumn = _ref.layoutColumn;
15
+ try {
16
+ var layoutSectionNode = layoutSection.createChecked(undefined, Fragment.fromArray(layoutContents.map(function (layoutContent) {
17
+ return layoutColumn.createChecked({
18
+ width: width
19
+ }, layoutContent);
20
+ })));
21
+ return layoutSectionNode;
22
+ } catch (error) {
23
+ // TODO analytics
24
+ }
25
+ return null;
26
+ };
27
+ export var moveToLayout = function moveToLayout(api) {
28
+ return function (from, to, position) {
29
+ return function (_ref2) {
30
+ var tr = _ref2.tr;
31
+ var _ref3 = tr.doc.type.schema.nodes || {},
32
+ layoutSection = _ref3.layoutSection,
33
+ layoutColumn = _ref3.layoutColumn,
34
+ doc = _ref3.doc;
35
+
36
+ // layout plugin does not exist
37
+ if (!layoutSection || !layoutColumn) {
38
+ return tr;
39
+ }
40
+ var $to = tr.doc.resolve(to);
41
+
42
+ // invalid to position or not top level.
43
+ if (!$to.nodeAfter || $to.parent.type !== doc) {
44
+ return tr;
45
+ }
46
+ var $from = tr.doc.resolve(from);
47
+
48
+ // invalid from position
49
+ if (!$from.nodeAfter) {
50
+ return tr;
51
+ }
52
+ var toNode = $to.nodeAfter;
53
+ var fromNode = $from.nodeAfter;
54
+ var fromNodeEndPos = from + fromNode.nodeSize;
55
+ var toNodeEndPos = to + toNode.nodeSize;
56
+ if ($to.nodeAfter.type !== layoutSection) {
57
+ var layoutContents = position === 'left' ? [fromNode, toNode] : [toNode, fromNode];
58
+ var newLayout = createNewLayout(tr.doc.type.schema, layoutContents);
59
+ if (newLayout) {
60
+ tr.delete(from, fromNodeEndPos);
61
+ var mappedTo = tr.mapping.map(to);
62
+ tr.delete(mappedTo, toNodeEndPos);
63
+ tr.insert(mappedTo, newLayout); // insert the content at the new position
64
+ }
65
+ return tr;
66
+ }
67
+ return tr;
68
+ };
69
+ };
70
+ };
@@ -4,4 +4,5 @@ export var DIRECTION = /*#__PURE__*/function (DIRECTION) {
4
4
  DIRECTION["LEFT"] = "left";
5
5
  DIRECTION["RIGHT"] = "right";
6
6
  return DIRECTION;
7
- }({});
7
+ }({});
8
+ export var MAX_LAYOUT_COLUMN_SUPPORTED = 3;
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  import { fg } from '@atlaskit/platform-feature-flags';
4
4
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
5
5
  import { moveNode } from './commands/move-node';
6
+ import { moveToLayout } from './commands/move-to-layout';
6
7
  import { createEmptyBlockExperimentPlugin } from './pm-plugins/empty-block-experiment';
7
8
  import { createPlugin, key } from './pm-plugins/main';
8
9
  import { DragHandleMenu } from './ui/drag-handle-menu';
@@ -31,6 +32,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
31
32
  },
32
33
  commands: {
33
34
  moveNode: moveNode(api),
35
+ moveToLayout: moveToLayout(api),
34
36
  showDragHandleAt: function showDragHandleAt(pos, anchorName, nodeType, handleOptions) {
35
37
  return function (_ref4) {
36
38
  var tr = _ref4.tr;
@@ -45,20 +47,9 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
45
47
  return tr;
46
48
  };
47
49
  },
48
- hideDragHandle: function hideDragHandle() {
50
+ setNodeDragged: function setNodeDragged(getPos, anchorName, nodeType) {
49
51
  return function (_ref5) {
50
52
  var tr = _ref5.tr;
51
- if (fg('confluence_frontend_page_title_enter_improvements')) {
52
- tr.setMeta(key, {
53
- hideDragHandle: true
54
- });
55
- }
56
- return tr;
57
- };
58
- },
59
- setNodeDragged: function setNodeDragged(getPos, anchorName, nodeType) {
60
- return function (_ref6) {
61
- var tr = _ref6.tr;
62
53
  var pos = getPos();
63
54
  if (pos === undefined) {
64
55
  return tr;
@@ -122,7 +122,7 @@ export var findNodeDecs = function findNodeDecs(decorations, from, to) {
122
122
  return spec.type === TYPE_NODE_DEC;
123
123
  });
124
124
  };
125
- export var createDropTargetDecoration = function createDropTargetDecoration(pos, props, side, anchorHeightsCache) {
125
+ export var createDropTargetDecoration = function createDropTargetDecoration(pos, props, side, anchorRectCache) {
126
126
  return Decoration.widget(pos, function (_, getPos) {
127
127
  var element = document.createElement('div');
128
128
  element.setAttribute('data-blocks-drop-target-container', 'true');
@@ -137,7 +137,7 @@ export var createDropTargetDecoration = function createDropTargetDecoration(pos,
137
137
  if (fg('platform_editor_drag_and_drop_target_v2')) {
138
138
  ReactDOM.render( /*#__PURE__*/createElement(DropTargetV2, _objectSpread(_objectSpread({}, props), {}, {
139
139
  getPos: getPos,
140
- anchorHeightsCache: anchorHeightsCache
140
+ anchorRectCache: anchorRectCache
141
141
  })), element);
142
142
  } else {
143
143
  ReactDOM.render( /*#__PURE__*/createElement(DropTarget, _objectSpread(_objectSpread({}, props), {}, {
@@ -150,7 +150,7 @@ export var createDropTargetDecoration = function createDropTargetDecoration(pos,
150
150
  side: side
151
151
  });
152
152
  };
153
- export var dropTargetDecorations = function dropTargetDecorations(newState, api, formatMessage, activeNode, anchorHeightsCache, from, to) {
153
+ export var dropTargetDecorations = function dropTargetDecorations(newState, api, formatMessage, activeNode, anchorRectCache, from, to) {
154
154
  unmountDecorations('data-blocks-drop-target-container');
155
155
  var decs = [];
156
156
  var POS_END_OF_DOC = newState.doc.nodeSize - 2;
@@ -159,7 +159,7 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
159
159
  var prevNode;
160
160
  var activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
161
161
  var activePMNode = typeof activeNodePos === 'number' && newState.doc.resolve(activeNodePos).nodeAfter;
162
- anchorHeightsCache === null || anchorHeightsCache === void 0 || anchorHeightsCache.clear();
162
+ anchorRectCache === null || anchorRectCache === void 0 || anchorRectCache.clear();
163
163
  var prevNodeStack = [];
164
164
  var popNodeStack = function popNodeStack(depth) {
165
165
  var result;
@@ -224,7 +224,7 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
224
224
  parentNode: parent || undefined,
225
225
  formatMessage: formatMessage,
226
226
  dropTargetStyle: shouldShowFullHeight ? 'fullHeight' : 'default'
227
- }, -1, anchorHeightsCache));
227
+ }, -1, anchorRectCache));
228
228
  if (endPos !== undefined) {
229
229
  decs.push(createDropTargetDecoration(endPos, {
230
230
  api: api,
@@ -232,7 +232,7 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
232
232
  parentNode: parent || undefined,
233
233
  formatMessage: formatMessage,
234
234
  dropTargetStyle: isInSupportedContainer ? 'fullHeight' : 'default'
235
- }, -1, anchorHeightsCache));
235
+ }, -1, anchorRectCache));
236
236
  }
237
237
  if (fg('platform_editor_drag_and_drop_target_v2')) {
238
238
  pushNodeStack(node, depth);
@@ -247,7 +247,7 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
247
247
  formatMessage: formatMessage,
248
248
  prevNode: newState.doc.lastChild || undefined,
249
249
  parentNode: newState.doc
250
- }, undefined, anchorHeightsCache));
250
+ }, undefined, anchorRectCache));
251
251
  }
252
252
  return decs;
253
253
  };
@@ -329,18 +329,22 @@ export var dragHandleDecoration = function dragHandleDecoration(api, formatMessa
329
329
  return Decoration.widget(pos, function (view, getPos) {
330
330
  var element = document.createElement('span');
331
331
  // Need to set it to inline to avoid text being split when merging two paragraphs
332
- element.style.display = 'inline';
332
+ // platform_editor_element_dnd_nested_fix_patch_2 -> inline decoration causes focus issues when refocusing Editor into first line
333
+ element.style.display = fg('platform_editor_element_dnd_nested_fix_patch_2') ? 'block' : 'inline';
333
334
  element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
334
335
  element.setAttribute('data-blocks-drag-handle-container', 'true');
335
336
  var isTopLevelNode = true;
336
337
  if (editorExperiment('nested-dnd', true)) {
337
- var $pos = view.state.doc.resolve(pos);
338
- isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
338
+ var newPos = fg('platform_editor_element_dnd_nested_fix_patch_3') ? getPos() : pos;
339
+ if (typeof newPos === 'number') {
340
+ var $pos = view.state.doc.resolve(newPos);
341
+ isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
342
+ }
339
343
  /*
340
344
  * We disable mouseover event to fix flickering issue on hover
341
345
  * However, the tooltip for nested drag handle is no long working.
342
346
  */
343
- if (!isTopLevelNode) {
347
+ if (newPos === undefined || !isTopLevelNode) {
344
348
  // This will also hide the tooltip.
345
349
  unbind = bind(element, {
346
350
  type: 'mouseover',
@@ -7,11 +7,6 @@ var isEmptyNestedParagraphOrHeading = function isEmptyNestedParagraphOrHeading(t
7
7
  }
8
8
  return false;
9
9
  };
10
- var isDocFirstChildEmptyLine = function isDocFirstChildEmptyLine(elem) {
11
- var _elem$firstElementChi;
12
- var parentElement = elem.parentElement;
13
- return (parentElement === null || parentElement === void 0 ? void 0 : parentElement.classList.contains('ProseMirror')) && (parentElement === null || parentElement === void 0 ? void 0 : parentElement.firstElementChild) === elem && ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6'].includes(elem.nodeName) && elem.childNodes.length === 1 && ((_elem$firstElementChi = elem.firstElementChild) === null || _elem$firstElementChi === void 0 ? void 0 : _elem$firstElementChi.classList.contains('ProseMirror-trailingBreak'));
14
- };
15
10
  export var handleMouseOver = function handleMouseOver(view, event, api) {
16
11
  var _api$blockControls, _target$classList;
17
12
  var _ref = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
@@ -30,11 +25,6 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
30
25
  var rootElement = target === null || target === void 0 ? void 0 : target.closest('[data-drag-handler-anchor-name]');
31
26
  if (rootElement) {
32
27
  var _rootElement$parentEl;
33
- if (isDocFirstChildEmptyLine(rootElement) && fg('confluence_frontend_page_title_enter_improvements')) {
34
- var _api$core, _api$blockControls2;
35
- 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 ? void 0 : _api$blockControls2.commands.hideDragHandle());
36
- return;
37
- }
38
28
  // We want to exlude handles from showing for empty paragraph and heading nodes
39
29
  if (editorExperiment('nested-dnd', true) && isEmptyNestedParagraphOrHeading(rootElement)) {
40
30
  return false;
@@ -83,8 +73,8 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
83
73
  }
84
74
  var nodeType = rootElement.getAttribute('data-drag-handler-node-type');
85
75
  if (nodeType) {
86
- var _api$core2, _api$blockControls3;
87
- api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.showDragHandleAt(rootPos, anchorName, nodeType));
76
+ var _api$core, _api$blockControls2;
77
+ 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 ? void 0 : _api$blockControls2.commands.showDragHandleAt(rootPos, anchorName, nodeType));
88
78
  }
89
79
  }
90
80
  };