@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
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.InlineHoverZone = exports.InlineDropTarget = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ var _react2 = require("@emotion/react");
11
+ var _hooks = require("@atlaskit/editor-common/hooks");
12
+ var _box = require("@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box");
13
+ var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
14
+ var _decorations = require("../pm-plugins/decorations");
15
+ var _anchorUtils = require("../utils/anchor-utils");
16
+ /* eslint-disable @atlaskit/design-system/consistent-css-prop-usage */
17
+ /* eslint-disable @atlaskit/ui-styling-standard/no-unsafe-values */
18
+ /**
19
+ * @jsxRuntime classic
20
+ * @jsx jsx
21
+ */
22
+
23
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
24
+
25
+ var dropTargetCommonStyle = (0, _react2.css)({
26
+ position: 'absolute',
27
+ display: 'block'
28
+ });
29
+ var hideDropTargetStyle = (0, _react2.css)({
30
+ display: 'none'
31
+ });
32
+ var hoverZoneCommonStyle = (0, _react2.css)({
33
+ position: 'absolute',
34
+ // same value as block hover zone
35
+ zIndex: 110
36
+ });
37
+
38
+ // gap between node boundary and drop indicator/drop zone
39
+ var GAP = 4;
40
+ var HOVER_ZONE_WIDTH_OFFSET = 40;
41
+ var HOVER_ZONE_HEIGHT_OFFSET = 10;
42
+ var HOVER_ZONE_DEFAULT_WIDTH = 40;
43
+ var InlineDropTarget = exports.InlineDropTarget = function InlineDropTarget(_ref) {
44
+ var api = _ref.api,
45
+ nextNode = _ref.nextNode,
46
+ position = _ref.position,
47
+ anchorRectCache = _ref.anchorRectCache;
48
+ var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['width']),
49
+ widthState = _useSharedPluginState.widthState;
50
+ var _useState = (0, _react.useState)(false),
51
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
52
+ isDraggedOver = _useState2[0],
53
+ setIsDraggedOver = _useState2[1];
54
+ var anchorName = nextNode ? (0, _decorations.getNodeAnchor)(nextNode) : '';
55
+ var handleDragEnter = (0, _react.useCallback)(function () {
56
+ setIsDraggedOver(true);
57
+ }, []);
58
+ var handleDragLeave = (0, _react.useCallback)(function () {
59
+ setIsDraggedOver(false);
60
+ }, []);
61
+ var dropTargetRectStyle = (0, _react.useMemo)(function () {
62
+ if ((0, _anchorUtils.isAnchorSupported)()) {
63
+ return (0, _react2.css)({
64
+ height: "calc(anchor-size(".concat(anchorName, " height))"),
65
+ positionAnchor: anchorName,
66
+ left: position === 'left' ? "calc(anchor(left) - ".concat(GAP, "px)") : "calc(anchor(right) + ".concat(GAP, "px)"),
67
+ top: "calc(anchor(top))"
68
+ });
69
+ }
70
+ var nodeRect = anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getRect(anchorName);
71
+ return (0, _react2.css)({
72
+ height: "calc(".concat((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.height) || 0, "px)"),
73
+ left: position === 'left' ? "".concat(((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.left) || 0) - GAP, "px") : "".concat(((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.right) || 0) + GAP, "px"),
74
+ top: "".concat((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.top) || 0, "px")
75
+ });
76
+ }, [anchorName, anchorRectCache, position]);
77
+ return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)("div", {
78
+ "data-test-id": "block-ctrl-drop-target-".concat(position),
79
+ css: [dropTargetCommonStyle, dropTargetRectStyle, !isDraggedOver && hideDropTargetStyle]
80
+ }, (0, _react2.jsx)(_box.DropIndicator, {
81
+ edge: position
82
+ })), (0, _react2.jsx)(InlineHoverZone, {
83
+ position: position,
84
+ node: nextNode,
85
+ editorWidthState: widthState,
86
+ anchorRectCache: anchorRectCache,
87
+ onDragEnter: handleDragEnter,
88
+ onDragLeave: handleDragLeave,
89
+ onDrop: function onDrop() {}
90
+ }));
91
+ };
92
+ var InlineHoverZone = exports.InlineHoverZone = function InlineHoverZone(_ref2) {
93
+ var node = _ref2.node,
94
+ editorWidthState = _ref2.editorWidthState,
95
+ anchorRectCache = _ref2.anchorRectCache,
96
+ position = _ref2.position,
97
+ onDragEnter = _ref2.onDragEnter,
98
+ onDragLeave = _ref2.onDragLeave,
99
+ onDrop = _ref2.onDrop;
100
+ var ref = (0, _react.useRef)(null);
101
+ var _ref3 = editorWidthState || {},
102
+ editorWith = _ref3.width;
103
+ var anchorName = node ? (0, _decorations.getNodeAnchor)(node) : '';
104
+ (0, _react.useEffect)(function () {
105
+ if (ref.current) {
106
+ return (0, _adapter.dropTargetForElements)({
107
+ element: ref.current,
108
+ onDragEnter: onDragEnter,
109
+ onDragLeave: onDragLeave,
110
+ onDrop: onDrop
111
+ });
112
+ }
113
+ }, [onDragEnter, onDragLeave, onDrop]);
114
+ var inlineHoverZoneRectStyle = (0, _react.useMemo)(function () {
115
+ if ((0, _anchorUtils.isAnchorSupported)()) {
116
+ return (0, _react2.css)({
117
+ positionAnchor: anchorName,
118
+ left: position === 'left' ? 'unset' : "calc(anchor(right) + ".concat(GAP, "px)"),
119
+ right: position === 'left' ? "calc(anchor(left) + ".concat(GAP, "px)") : 'unset',
120
+ top: "calc(anchor(top))",
121
+ width: editorWith ? "calc((".concat(editorWith, "px - anchor-size(").concat(anchorName, " width))/2 - ").concat(HOVER_ZONE_WIDTH_OFFSET, "px)") : "".concat(HOVER_ZONE_DEFAULT_WIDTH, "px"),
122
+ height: "calc(anchor-size(".concat(anchorName, " height))")
123
+ });
124
+ }
125
+ var nodeRect = anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getRect(anchorName);
126
+ var width = editorWith ? (editorWith - ((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.width) || 0)) / 2 - HOVER_ZONE_WIDTH_OFFSET : HOVER_ZONE_DEFAULT_WIDTH;
127
+ return (0, _react2.css)({
128
+ left: position === 'left' ? "".concat(((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.left) || 0) - width - GAP, "px") : "".concat(((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.right) || 0) + GAP, "px"),
129
+ top: "".concat((nodeRect === null || nodeRect === void 0 ? void 0 : nodeRect.top) || 0, "px"),
130
+ width: "".concat(width, "px"),
131
+ height: "calc(".concat((anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getHeight(anchorName)) || 0, "px - ").concat(HOVER_ZONE_HEIGHT_OFFSET, "px)")
132
+ });
133
+ }, [anchorName, anchorRectCache, editorWith, position]);
134
+ return (0, _react2.jsx)("div", {
135
+ ref: ref,
136
+ css: [hoverZoneCommonStyle, inlineHoverZoneRectStyle]
137
+ });
138
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isPreRelease1 = void 0;
7
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
8
+ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
9
+ var isPreRelease1 = exports.isPreRelease1 = function isPreRelease1() {
10
+ return (0, _experiments.editorExperiment)('advanced_layouts', true) || (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_pre_release_1');
11
+ };
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.isAnchorSupported = exports.AnchorHeightsCache = void 0;
7
+ exports.isAnchorSupported = exports.AnchorRectCache = void 0;
8
8
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
9
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
@@ -18,36 +18,42 @@ var isAnchorSupported = exports.isAnchorSupported = (0, _memoizeOne.default)(fun
18
18
  }
19
19
  return false;
20
20
  });
21
- var AnchorHeightsCache = exports.AnchorHeightsCache = /*#__PURE__*/function () {
22
- function AnchorHeightsCache() {
23
- (0, _classCallCheck2.default)(this, AnchorHeightsCache);
24
- (0, _defineProperty2.default)(this, "anchorHeightsMap", {});
21
+ var AnchorRectCache = exports.AnchorRectCache = /*#__PURE__*/function () {
22
+ function AnchorRectCache() {
23
+ (0, _classCallCheck2.default)(this, AnchorRectCache);
24
+ (0, _defineProperty2.default)(this, "anchorRectMap", {});
25
25
  (0, _defineProperty2.default)(this, "isAnchorSupported", isAnchorSupported());
26
26
  (0, _defineProperty2.default)(this, "isDirty", true);
27
27
  (0, _defineProperty2.default)(this, "view", null);
28
28
  }
29
- (0, _createClass2.default)(AnchorHeightsCache, [{
29
+ (0, _createClass2.default)(AnchorRectCache, [{
30
30
  key: "clear",
31
31
  value: function clear() {
32
32
  this.isDirty = true;
33
- this.anchorHeightsMap = {};
33
+ this.anchorRectMap = {};
34
34
  }
35
35
  }, {
36
- key: "getHeights",
37
- value: function getHeights() {
36
+ key: "getRects",
37
+ value: function getRects() {
38
38
  if (this.isDirty) {
39
39
  var _this$view;
40
40
  var anchorElements = ((_this$view = this.view) === null || _this$view === void 0 ? void 0 : _this$view.dom.querySelectorAll('[data-drag-handler-anchor-name]')) || [];
41
- this.anchorHeightsMap = Array.from(anchorElements).reduce(function (prev, curr) {
41
+ this.anchorRectMap = Array.from(anchorElements).reduce(function (prev, curr) {
42
42
  var anchorName = curr.getAttribute('data-drag-handler-anchor-name');
43
43
  if (anchorName) {
44
- return _objectSpread(_objectSpread({}, prev), {}, (0, _defineProperty2.default)({}, anchorName, curr.clientHeight));
44
+ return _objectSpread(_objectSpread({}, prev), {}, (0, _defineProperty2.default)({}, anchorName, {
45
+ height: curr.clientHeight,
46
+ top: curr.offsetTop,
47
+ left: curr.offsetLeft,
48
+ right: curr.offsetLeft + curr.clientWidth,
49
+ width: curr.clientWidth
50
+ }));
45
51
  }
46
52
  return prev;
47
53
  }, {});
48
54
  this.isDirty = false;
49
55
  }
50
- return this.anchorHeightsMap;
56
+ return this.anchorRectMap;
51
57
  }
52
58
  }, {
53
59
  key: "setEditorView",
@@ -59,12 +65,62 @@ var AnchorHeightsCache = exports.AnchorHeightsCache = /*#__PURE__*/function () {
59
65
  }, {
60
66
  key: "getHeight",
61
67
  value: function getHeight(anchorName) {
68
+ var _rects$anchorName;
62
69
  if (this.isAnchorSupported) {
63
70
  return null;
64
71
  }
65
- var heights = this.getHeights();
66
- return heights[anchorName];
72
+ var rects = this.getRects();
73
+ return (_rects$anchorName = rects[anchorName]) === null || _rects$anchorName === void 0 ? void 0 : _rects$anchorName.height;
74
+ }
75
+ }, {
76
+ key: "getWidth",
77
+ value: function getWidth(anchorName) {
78
+ var _rects$anchorName2;
79
+ if (this.isAnchorSupported) {
80
+ return null;
81
+ }
82
+ var rects = this.getRects();
83
+ return (_rects$anchorName2 = rects[anchorName]) === null || _rects$anchorName2 === void 0 ? void 0 : _rects$anchorName2.width;
84
+ }
85
+ }, {
86
+ key: "getLeft",
87
+ value: function getLeft(anchorName) {
88
+ var _rects$anchorName3;
89
+ if (this.isAnchorSupported) {
90
+ return null;
91
+ }
92
+ var rects = this.getRects();
93
+ return (_rects$anchorName3 = rects[anchorName]) === null || _rects$anchorName3 === void 0 ? void 0 : _rects$anchorName3.left;
94
+ }
95
+ }, {
96
+ key: "getTop",
97
+ value: function getTop(anchorName) {
98
+ var _rects$anchorName4;
99
+ if (this.isAnchorSupported) {
100
+ return null;
101
+ }
102
+ var rects = this.getRects();
103
+ return (_rects$anchorName4 = rects[anchorName]) === null || _rects$anchorName4 === void 0 ? void 0 : _rects$anchorName4.top;
104
+ }
105
+ }, {
106
+ key: "getRight",
107
+ value: function getRight(anchorName) {
108
+ var _rects$anchorName5;
109
+ if (this.isAnchorSupported) {
110
+ return null;
111
+ }
112
+ var rects = this.getRects();
113
+ return (_rects$anchorName5 = rects[anchorName]) === null || _rects$anchorName5 === void 0 ? void 0 : _rects$anchorName5.right;
114
+ }
115
+ }, {
116
+ key: "getRect",
117
+ value: function getRect(anchorName) {
118
+ if (this.isAnchorSupported) {
119
+ return null;
120
+ }
121
+ var rects = this.getRects();
122
+ return rects[anchorName];
67
123
  }
68
124
  }]);
69
- return AnchorHeightsCache;
125
+ return AnchorRectCache;
70
126
  }();
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.shouldAllowInlineDropTarget = void 0;
7
+ var _utils = require("@atlaskit/editor-common/utils");
8
+ var _consts = require("../consts");
9
+ var _advancedLayoutsFlags = require("./advanced-layouts-flags");
10
+ var shouldAllowInlineDropTarget = exports.shouldAllowInlineDropTarget = function shouldAllowInlineDropTarget(isNested, node) {
11
+ if (!(0, _advancedLayoutsFlags.isPreRelease1)() || isNested) {
12
+ return false;
13
+ }
14
+ if ((node === null || node === void 0 ? void 0 : node.type.name) === 'layoutSection') {
15
+ return node.childCount < _consts.MAX_LAYOUT_COLUMN_SUPPORTED;
16
+ }
17
+ return !(0, _utils.isEmptyParagraph)(node);
18
+ };
@@ -0,0 +1,69 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
+ import { DEFAULT_COLUMN_DISTRIBUTIONS } from '../ui/consts';
3
+ const createNewLayout = (schema, layoutContents) => {
4
+ // TODO update with constant
5
+ if (layoutContents.length === 0 || layoutContents.length > 5) {
6
+ return null;
7
+ }
8
+ const width = DEFAULT_COLUMN_DISTRIBUTIONS[layoutContents.length];
9
+ if (!width) {
10
+ return null;
11
+ }
12
+ const {
13
+ layoutSection,
14
+ layoutColumn
15
+ } = schema.nodes || {};
16
+ try {
17
+ const layoutSectionNode = layoutSection.createChecked(undefined, Fragment.fromArray(layoutContents.map(layoutContent => {
18
+ return layoutColumn.createChecked({
19
+ width
20
+ }, layoutContent);
21
+ })));
22
+ return layoutSectionNode;
23
+ } catch (error) {
24
+ // TODO analytics
25
+ }
26
+ return null;
27
+ };
28
+ export const moveToLayout = api => (from, to, position) => ({
29
+ tr
30
+ }) => {
31
+ const {
32
+ layoutSection,
33
+ layoutColumn,
34
+ doc
35
+ } = tr.doc.type.schema.nodes || {};
36
+
37
+ // layout plugin does not exist
38
+ if (!layoutSection || !layoutColumn) {
39
+ return tr;
40
+ }
41
+ const $to = tr.doc.resolve(to);
42
+
43
+ // invalid to position or not top level.
44
+ if (!$to.nodeAfter || $to.parent.type !== doc) {
45
+ return tr;
46
+ }
47
+ const $from = tr.doc.resolve(from);
48
+
49
+ // invalid from position
50
+ if (!$from.nodeAfter) {
51
+ return tr;
52
+ }
53
+ const toNode = $to.nodeAfter;
54
+ const fromNode = $from.nodeAfter;
55
+ const fromNodeEndPos = from + fromNode.nodeSize;
56
+ const toNodeEndPos = to + toNode.nodeSize;
57
+ if ($to.nodeAfter.type !== layoutSection) {
58
+ const layoutContents = position === 'left' ? [fromNode, toNode] : [toNode, fromNode];
59
+ const newLayout = createNewLayout(tr.doc.type.schema, layoutContents);
60
+ if (newLayout) {
61
+ tr.delete(from, fromNodeEndPos);
62
+ const mappedTo = tr.mapping.map(to);
63
+ tr.delete(mappedTo, toNodeEndPos);
64
+ tr.insert(mappedTo, newLayout); // insert the content at the new position
65
+ }
66
+ return tr;
67
+ }
68
+ return tr;
69
+ };
@@ -4,4 +4,5 @@ export let DIRECTION = /*#__PURE__*/function (DIRECTION) {
4
4
  DIRECTION["LEFT"] = "left";
5
5
  DIRECTION["RIGHT"] = "right";
6
6
  return DIRECTION;
7
- }({});
7
+ }({});
8
+ export const MAX_LAYOUT_COLUMN_SUPPORTED = 3;
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
4
4
  import { moveNode } from './commands/move-node';
5
+ import { moveToLayout } from './commands/move-to-layout';
5
6
  import { createEmptyBlockExperimentPlugin } from './pm-plugins/empty-block-experiment';
6
7
  import { createPlugin, key } from './pm-plugins/main';
7
8
  import { DragHandleMenu } from './ui/drag-handle-menu';
@@ -28,6 +29,7 @@ export const blockControlsPlugin = ({
28
29
  },
29
30
  commands: {
30
31
  moveNode: moveNode(api),
32
+ moveToLayout: moveToLayout(api),
31
33
  showDragHandleAt: (pos, anchorName, nodeType, handleOptions) => ({
32
34
  tr
33
35
  }) => {
@@ -41,16 +43,6 @@ export const blockControlsPlugin = ({
41
43
  });
42
44
  return tr;
43
45
  },
44
- hideDragHandle: () => ({
45
- tr
46
- }) => {
47
- if (fg('confluence_frontend_page_title_enter_improvements')) {
48
- tr.setMeta(key, {
49
- hideDragHandle: true
50
- });
51
- }
52
- return tr;
53
- },
54
46
  setNodeDragged: (getPos, anchorName, nodeType) => ({
55
47
  tr
56
48
  }) => {
@@ -110,7 +110,7 @@ export const findNodeDecs = (decorations, from, to) => {
110
110
  }
111
111
  return decorations.find(newfrom, newTo, spec => spec.type === TYPE_NODE_DEC);
112
112
  };
113
- export const createDropTargetDecoration = (pos, props, side, anchorHeightsCache) => {
113
+ export const createDropTargetDecoration = (pos, props, side, anchorRectCache) => {
114
114
  return Decoration.widget(pos, (_, getPos) => {
115
115
  const element = document.createElement('div');
116
116
  element.setAttribute('data-blocks-drop-target-container', 'true');
@@ -127,7 +127,7 @@ export const createDropTargetDecoration = (pos, props, side, anchorHeightsCache)
127
127
  ReactDOM.render( /*#__PURE__*/createElement(DropTargetV2, {
128
128
  ...props,
129
129
  getPos,
130
- anchorHeightsCache
130
+ anchorRectCache
131
131
  }), element);
132
132
  } else {
133
133
  ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
@@ -141,7 +141,7 @@ export const createDropTargetDecoration = (pos, props, side, anchorHeightsCache)
141
141
  side
142
142
  });
143
143
  };
144
- export const dropTargetDecorations = (newState, api, formatMessage, activeNode, anchorHeightsCache, from, to) => {
144
+ export const dropTargetDecorations = (newState, api, formatMessage, activeNode, anchorRectCache, from, to) => {
145
145
  unmountDecorations('data-blocks-drop-target-container');
146
146
  const decs = [];
147
147
  const POS_END_OF_DOC = newState.doc.nodeSize - 2;
@@ -150,7 +150,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
150
150
  let prevNode;
151
151
  const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
152
152
  const activePMNode = typeof activeNodePos === 'number' && newState.doc.resolve(activeNodePos).nodeAfter;
153
- anchorHeightsCache === null || anchorHeightsCache === void 0 ? void 0 : anchorHeightsCache.clear();
153
+ anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.clear();
154
154
  const prevNodeStack = [];
155
155
  const popNodeStack = depth => {
156
156
  let result;
@@ -215,7 +215,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
215
215
  parentNode: parent || undefined,
216
216
  formatMessage,
217
217
  dropTargetStyle: shouldShowFullHeight ? 'fullHeight' : 'default'
218
- }, -1, anchorHeightsCache));
218
+ }, -1, anchorRectCache));
219
219
  if (endPos !== undefined) {
220
220
  decs.push(createDropTargetDecoration(endPos, {
221
221
  api,
@@ -223,7 +223,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
223
223
  parentNode: parent || undefined,
224
224
  formatMessage,
225
225
  dropTargetStyle: isInSupportedContainer ? 'fullHeight' : 'default'
226
- }, -1, anchorHeightsCache));
226
+ }, -1, anchorRectCache));
227
227
  }
228
228
  if (fg('platform_editor_drag_and_drop_target_v2')) {
229
229
  pushNodeStack(node, depth);
@@ -238,7 +238,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
238
238
  formatMessage,
239
239
  prevNode: newState.doc.lastChild || undefined,
240
240
  parentNode: newState.doc
241
- }, undefined, anchorHeightsCache));
241
+ }, undefined, anchorRectCache));
242
242
  }
243
243
  return decs;
244
244
  };
@@ -316,18 +316,22 @@ export const dragHandleDecoration = (api, formatMessage, pos, anchorName, nodeTy
316
316
  return Decoration.widget(pos, (view, getPos) => {
317
317
  const element = document.createElement('span');
318
318
  // Need to set it to inline to avoid text being split when merging two paragraphs
319
- element.style.display = 'inline';
319
+ // platform_editor_element_dnd_nested_fix_patch_2 -> inline decoration causes focus issues when refocusing Editor into first line
320
+ element.style.display = fg('platform_editor_element_dnd_nested_fix_patch_2') ? 'block' : 'inline';
320
321
  element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
321
322
  element.setAttribute('data-blocks-drag-handle-container', 'true');
322
323
  let isTopLevelNode = true;
323
324
  if (editorExperiment('nested-dnd', true)) {
324
- const $pos = view.state.doc.resolve(pos);
325
- isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
325
+ const newPos = fg('platform_editor_element_dnd_nested_fix_patch_3') ? getPos() : pos;
326
+ if (typeof newPos === 'number') {
327
+ const $pos = view.state.doc.resolve(newPos);
328
+ isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
329
+ }
326
330
  /*
327
331
  * We disable mouseover event to fix flickering issue on hover
328
332
  * However, the tooltip for nested drag handle is no long working.
329
333
  */
330
- if (!isTopLevelNode) {
334
+ if (newPos === undefined || !isTopLevelNode) {
331
335
  // This will also hide the tooltip.
332
336
  unbind = bind(element, {
333
337
  type: 'mouseover',
@@ -7,11 +7,6 @@ const isEmptyNestedParagraphOrHeading = target => {
7
7
  }
8
8
  return false;
9
9
  };
10
- const isDocFirstChildEmptyLine = elem => {
11
- var _elem$firstElementChi;
12
- const 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 const handleMouseOver = (view, event, api) => {
16
11
  var _api$blockControls, _target$classList;
17
12
  const {
@@ -31,11 +26,6 @@ export const handleMouseOver = (view, event, api) => {
31
26
  let rootElement = target === null || target === void 0 ? void 0 : target.closest('[data-drag-handler-anchor-name]');
32
27
  if (rootElement) {
33
28
  var _rootElement$parentEl;
34
- if (isDocFirstChildEmptyLine(rootElement) && fg('confluence_frontend_page_title_enter_improvements')) {
35
- var _api$core, _api$blockControls2;
36
- api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.hideDragHandle());
37
- return;
38
- }
39
29
  // We want to exlude handles from showing for empty paragraph and heading nodes
40
30
  if (editorExperiment('nested-dnd', true) && isEmptyNestedParagraphOrHeading(rootElement)) {
41
31
  return false;
@@ -84,8 +74,8 @@ export const handleMouseOver = (view, event, api) => {
84
74
  }
85
75
  const nodeType = rootElement.getAttribute('data-drag-handler-node-type');
86
76
  if (nodeType) {
87
- var _api$core2, _api$blockControls3;
88
- api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.showDragHandleAt(rootPos, anchorName, nodeType));
77
+ var _api$core, _api$blockControls2;
78
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.showDragHandleAt(rootPos, anchorName, nodeType));
89
79
  }
90
80
  }
91
81
  };
@@ -11,7 +11,7 @@ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-sc
11
11
  import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
12
12
  import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
13
13
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
14
- import { AnchorHeightsCache, isAnchorSupported } from '../utils/anchor-utils';
14
+ import { AnchorRectCache, isAnchorSupported } from '../utils/anchor-utils';
15
15
  import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
16
16
  import { getTrMetadata } from '../utils/transactions';
17
17
  import { dragHandleDecoration, dropTargetDecorations, emptyParagraphNodeDecorations, findDropTargetDecs, findHandleDec, findNodeDecs, nodeDecorations } from './decorations';
@@ -89,11 +89,8 @@ const initialState = {
89
89
  isDocSizeLimitEnabled: null,
90
90
  isPMDragging: false
91
91
  };
92
- export const newApply = (api, formatMessage, tr, currentState, newState, flags, anchorHeightsCache) => {
92
+ export const newApply = (api, formatMessage, tr, currentState, newState, flags, anchorRectCache) => {
93
93
  var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
94
- const {
95
- isTitleEnterImprovementEnabled
96
- } = flags;
97
94
  let {
98
95
  activeNode,
99
96
  decorations,
@@ -176,7 +173,7 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
176
173
  const shouldRecreateHandle = latestActiveNode && (activeNodeChanged || isActiveNodeModified || editorSizeChanged || handleNeedsRedraw);
177
174
 
178
175
  // Remove handle dec when explicitly hidden, a node is resizing, activeNode pos was deleted, or DnD moved a node
179
- const shouldRemoveHandle = latestActiveNode && ((meta === null || meta === void 0 ? void 0 : meta.hideDragHandle) && isTitleEnterImprovementEnabled || isResizerResizing || isActiveNodeDeleted || (meta === null || meta === void 0 ? void 0 : meta.nodeMoved));
176
+ const shouldRemoveHandle = latestActiveNode && (isResizerResizing || isActiveNodeDeleted || (meta === null || meta === void 0 ? void 0 : meta.nodeMoved));
180
177
  if (shouldRemoveHandle) {
181
178
  var _activeNode3, _activeNode4;
182
179
  const oldHandle = findHandleDec(decorations, (_activeNode3 = activeNode) === null || _activeNode3 === void 0 ? void 0 : _activeNode3.pos, (_activeNode4 = activeNode) === null || _activeNode4 === void 0 ? void 0 : _activeNode4.pos);
@@ -201,7 +198,7 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
201
198
  // Add drop targets when dragging starts or some are missing
202
199
  if (api) {
203
200
  if (meta !== null && meta !== void 0 && meta.isDragging || isDropTargetsMissing || isBlocksDragTargetDebug()) {
204
- const decs = dropTargetDecorations(newState, api, formatMessage, latestActiveNode, anchorHeightsCache);
201
+ const decs = dropTargetDecorations(newState, api, formatMessage, latestActiveNode, anchorRectCache);
205
202
  decorations = decorations.add(newState.doc, decs);
206
203
  }
207
204
  }
@@ -226,11 +223,10 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
226
223
  isPMDragging: (_meta$isPMDragging = meta === null || meta === void 0 ? void 0 : meta.isPMDragging) !== null && _meta$isPMDragging !== void 0 ? _meta$isPMDragging : isPMDragging
227
224
  };
228
225
  };
229
- export const oldApply = (api, formatMessage, tr, currentState, oldState, newState, flags, anchorHeightsCache) => {
226
+ export const oldApply = (api, formatMessage, tr, currentState, oldState, newState, flags, anchorRectCache) => {
230
227
  var _meta$activeNode2, _meta$activeNode$hand2, _activeNodeWithNewNod, _meta$activeNode8, _meta$isDragging4, _meta$editorHeight2, _meta$editorWidthLeft2, _meta$editorWidthRigh2, _meta$isPMDragging2;
231
228
  const {
232
- isNestedEnabled,
233
- isTitleEnterImprovementEnabled
229
+ isNestedEnabled
234
230
  } = flags;
235
231
  let {
236
232
  activeNode,
@@ -264,7 +260,7 @@ export const oldApply = (api, formatMessage, tr, currentState, oldState, newStat
264
260
  // During resize, remove the drag handle widget so its dom positioning doesn't need to be maintained
265
261
  // Also remove the handle when the node is moved or the node count changes. This helps prevent incorrect positioning
266
262
  // Don't remove the handle if remote changes are changing the node count, its prosemirror position can be mapped instead
267
- if (meta !== null && meta !== void 0 && meta.hideDragHandle && isTitleEnterImprovementEnabled || isResizerResizing || maybeNodeCountChanged && shouldRemoveHandle || meta !== null && meta !== void 0 && meta.nodeMoved) {
263
+ if (isResizerResizing || maybeNodeCountChanged && shouldRemoveHandle || meta !== null && meta !== void 0 && meta.nodeMoved) {
268
264
  const oldHandle = decorations.find(undefined, undefined, spec => spec.type === 'drag-handle');
269
265
  decorations = decorations.remove(oldHandle);
270
266
  }
@@ -371,7 +367,7 @@ export const oldApply = (api, formatMessage, tr, currentState, oldState, newStat
371
367
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
372
368
  if (shouldCreateDropTargets || isBlocksDragTargetDebug()) {
373
369
  var _meta$activeNode7;
374
- const decs = dropTargetDecorations(newState, api, formatMessage, isNestedEnabled ? (_meta$activeNode7 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode7 !== void 0 ? _meta$activeNode7 : mappedActiveNodePos : meta === null || meta === void 0 ? void 0 : meta.activeNode, anchorHeightsCache);
370
+ const decs = dropTargetDecorations(newState, api, formatMessage, isNestedEnabled ? (_meta$activeNode7 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode7 !== void 0 ? _meta$activeNode7 : mappedActiveNodePos : meta === null || meta === void 0 ? void 0 : meta.activeNode, anchorRectCache);
375
371
  decorations = decorations.add(newState.doc, decs);
376
372
  }
377
373
  }
@@ -406,18 +402,16 @@ export const createPlugin = (api, getIntl) => {
406
402
  const isOptimisedApply = isNestedEnabled && editorExperiment('optimised-apply-dnd', true, {
407
403
  exposure: true
408
404
  });
409
- const isTitleEnterImprovementEnabled = fg('confluence_frontend_page_title_enter_improvements');
410
405
  const flags = {
411
406
  isNestedEnabled,
412
- isOptimisedApply,
413
- isTitleEnterImprovementEnabled
407
+ isOptimisedApply
414
408
  };
415
409
  if (fg('platform_editor_element_dnd_nested_fix_patch_2')) {
416
410
  // TODO: Remove this once FG is used in code
417
411
  }
418
- let anchorHeightsCache;
412
+ let anchorRectCache;
419
413
  if (!isAnchorSupported() && fg('platform_editor_drag_and_drop_target_v2')) {
420
- anchorHeightsCache = new AnchorHeightsCache();
414
+ anchorRectCache = new AnchorRectCache();
421
415
  }
422
416
  return new SafePlugin({
423
417
  key,
@@ -427,9 +421,9 @@ export const createPlugin = (api, getIntl) => {
427
421
  },
428
422
  apply(tr, currentState, oldState, newState) {
429
423
  if (isOptimisedApply) {
430
- return newApply(api, formatMessage, tr, currentState, newState, flags, anchorHeightsCache);
424
+ return newApply(api, formatMessage, tr, currentState, newState, flags, anchorRectCache);
431
425
  }
432
- return oldApply(api, formatMessage, tr, currentState, oldState, newState, flags, anchorHeightsCache);
426
+ return oldApply(api, formatMessage, tr, currentState, oldState, newState, flags, anchorRectCache);
433
427
  }
434
428
  },
435
429
  props: {
@@ -481,8 +475,8 @@ export const createPlugin = (api, getIntl) => {
481
475
  return false;
482
476
  },
483
477
  dragstart(view) {
484
- var _anchorHeightsCache;
485
- (_anchorHeightsCache = anchorHeightsCache) === null || _anchorHeightsCache === void 0 ? void 0 : _anchorHeightsCache.setEditorView(view);
478
+ var _anchorRectCache;
479
+ (_anchorRectCache = anchorRectCache) === null || _anchorRectCache === void 0 ? void 0 : _anchorRectCache.setEditorView(view);
486
480
  view.dispatch(view.state.tr.setMeta(key, {
487
481
  isPMDragging: true
488
482
  }));
@@ -175,4 +175,11 @@ export const nodeMargins = {
175
175
  top: 0,
176
176
  bottom: 0
177
177
  }
178
+ };
179
+ export const DEFAULT_COLUMN_DISTRIBUTIONS = {
180
+ 1: 100,
181
+ 2: 50,
182
+ 3: 33.33,
183
+ 4: 25,
184
+ 5: 20
178
185
  };