@atlaskit/editor-plugin-block-controls 2.2.2 → 2.3.1

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.
@@ -8,8 +8,10 @@ import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
8
8
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
11
+ import { nodeMargins } from '../ui/consts';
11
12
  import { DragHandle } from '../ui/drag-handle';
12
13
  import { DropTarget } from '../ui/drop-target';
14
+ import { DropTargetV2, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET } from '../ui/drop-target-v2';
13
15
  import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
14
16
  import { canMoveNodeToIndex } from '../utils/validation';
15
17
  const IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn', 'listItem', 'caption'];
@@ -17,24 +19,104 @@ const IGNORE_NODE_DESCENDANTS = ['listItem', 'taskList', 'decisionList', 'mediaS
17
19
  const PARENT_WITH_END_DROP_TARGET = ['tableCell', 'tableHeader', 'panel', 'layoutColumn', 'expand', 'nestedExpand', 'bodiedExtension'];
18
20
  const DISABLE_CHILD_DROP_TARGET = ['orderedList', 'bulletList'];
19
21
  const getNestedDepth = () => editorExperiment('nested-dnd', true) ? 100 : 0;
20
- const createDropTargetDecoration = (pos, dropTargetDec) => {
22
+ export const getNodeAnchor = node => {
23
+ const handleId = ObjHash.getForNode(node);
24
+ return `--node-anchor-${node.type.name}-${handleId}`;
25
+ };
26
+ const getNodeMargins = node => {
27
+ if (!node) {
28
+ return nodeMargins['default'];
29
+ }
30
+ const nodeTypeName = node.type.name;
31
+ if (nodeTypeName === 'heading') {
32
+ return nodeMargins[`heading${node.attrs.level}`] || nodeMargins['default'];
33
+ }
34
+ return nodeMargins[nodeTypeName] || nodeMargins['default'];
35
+ };
36
+ const getGapAndOffset = (prevNode, nextNode, parentNode) => {
37
+ if (!prevNode && nextNode) {
38
+ // first node
39
+ return {
40
+ gap: 0,
41
+ offset: 0
42
+ };
43
+ } else if (prevNode && !nextNode) {
44
+ return {
45
+ gap: 0,
46
+ offset: 0
47
+ };
48
+ }
49
+ const top = getNodeMargins(nextNode).top || 4;
50
+ const bottom = getNodeMargins(prevNode).bottom || 4;
51
+ const gap = Math.max(top, bottom);
52
+ let offset = top - gap / 2;
53
+ if ((prevNode === null || prevNode === void 0 ? void 0 : prevNode.type.name) === 'mediaSingle' && (nextNode === null || nextNode === void 0 ? void 0 : nextNode.type.name) === 'mediaSingle') {
54
+ offset = -offset;
55
+ } else if (prevNode !== null && prevNode !== void 0 && prevNode.type.name && ['tableCell', 'tableHeader'].includes(prevNode === null || prevNode === void 0 ? void 0 : prevNode.type.name)) {
56
+ offset = 0;
57
+ }
58
+ return {
59
+ gap,
60
+ offset
61
+ };
62
+ };
63
+ const shouldDescend = node => {
64
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
65
+ return !['mediaSingle', 'paragraph', 'heading'].includes(node.type.name);
66
+ }
67
+ return true;
68
+ };
69
+ export const createDropTargetDecoration = (pos, props, side, anchorHeightsCache) => {
21
70
  return Decoration.widget(pos, (_, getPos) => {
22
71
  const element = document.createElement('div');
23
72
  element.setAttribute('data-blocks-drop-target-container', 'true');
24
73
  element.style.clear = 'unset';
25
- ReactDOM.render(dropTargetDec(getPos), element);
74
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
75
+ const {
76
+ gap,
77
+ offset
78
+ } = getGapAndOffset(props.prevNode, props.nextNode, props.parentNode);
79
+ element.style.setProperty(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET, `${offset}px`);
80
+ element.style.setProperty(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, `${gap}px`);
81
+ }
82
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
83
+ ReactDOM.render( /*#__PURE__*/createElement(DropTargetV2, {
84
+ ...props,
85
+ getPos,
86
+ anchorHeightsCache
87
+ }), element);
88
+ } else {
89
+ ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
90
+ ...props,
91
+ getPos
92
+ }), element);
93
+ }
26
94
  return element;
27
95
  }, {
28
96
  type: 'drop-target-decoration',
29
- side: -1
97
+ side
30
98
  });
31
99
  };
32
- export const dropTargetDecorations = (newState, api, formatMessage, activeNode) => {
100
+ export const dropTargetDecorations = (newState, api, formatMessage, activeNode, anchorHeightsCache) => {
33
101
  const decs = [];
34
102
  unmountDecorations('data-blocks-drop-target-container');
35
103
  let prevNode;
36
104
  const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
37
105
  const activePMNode = typeof activeNodePos === 'number' && newState.doc.resolve(activeNodePos).nodeAfter;
106
+ anchorHeightsCache === null || anchorHeightsCache === void 0 ? void 0 : anchorHeightsCache.clear();
107
+ const prevNodeStack = [];
108
+ const popNodeStack = depth => {
109
+ let result;
110
+ const toDepth = Math.max(depth, 0);
111
+ while (prevNodeStack.length > toDepth) {
112
+ result = prevNodeStack.pop();
113
+ }
114
+ return result;
115
+ };
116
+ const pushNodeStack = (node, depth) => {
117
+ popNodeStack(depth);
118
+ prevNodeStack.push(node);
119
+ };
38
120
  newState.doc.descendants((node, pos, parent, index) => {
39
121
  let depth = 0;
40
122
  // drop target deco at the end position
@@ -42,58 +124,65 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode)
42
124
  if (editorExperiment('nested-dnd', true)) {
43
125
  depth = newState.doc.resolve(pos).depth;
44
126
  if (node.isInline || !parent || DISABLE_CHILD_DROP_TARGET.includes(parent.type.name)) {
45
- prevNode = node;
127
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
128
+ pushNodeStack(node, depth);
129
+ } else {
130
+ prevNode = node;
131
+ }
46
132
  return false;
47
133
  }
48
134
  if (IGNORE_NODES.includes(node.type.name)) {
49
- prevNode = node;
50
- return true; //skip over, don't consider it a valid depth
135
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
136
+ pushNodeStack(node, depth);
137
+ } else {
138
+ prevNode = node;
139
+ }
140
+ return shouldDescend(node); //skip over, don't consider it a valid depth
51
141
  }
52
142
  const canDrop = activePMNode && canMoveNodeToIndex(parent, index, activePMNode);
53
143
 
54
144
  //NOTE: This will block drop targets showing for nodes that are valid after transformation (i.e. expand -> nestedExpand)
55
145
  if (!canDrop && !isBlocksDragTargetDebug()) {
56
- prevNode = node;
146
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
147
+ pushNodeStack(node, depth);
148
+ } else {
149
+ prevNode = node;
150
+ }
57
151
  return false; //not valid pos, so nested not valid either
58
152
  }
59
153
  if (parent.lastChild === node && !isEmptyParagraph(node) && PARENT_WITH_END_DROP_TARGET.includes(parent.type.name)) {
60
154
  endPos = pos + node.nodeSize;
61
155
  }
62
156
  }
63
- const previousNode = prevNode; // created scoped variable
64
- decs.push(createDropTargetDecoration(pos, getPos => /*#__PURE__*/createElement(DropTarget, {
157
+ const previousNode = fg('platform_editor_drag_and_drop_target_v2') ? popNodeStack(depth) : prevNode; // created scoped variable
158
+ decs.push(createDropTargetDecoration(pos, {
65
159
  api,
66
- getPos,
67
160
  prevNode: previousNode,
68
161
  nextNode: node,
69
- parentNode: parent,
162
+ parentNode: parent || undefined,
70
163
  formatMessage
71
- })));
164
+ }, -1, anchorHeightsCache));
72
165
  if (endPos !== undefined) {
73
- decs.push(createDropTargetDecoration(endPos, getPos => /*#__PURE__*/createElement(DropTarget, {
166
+ decs.push(createDropTargetDecoration(endPos, {
74
167
  api,
75
- getPos,
76
- parentNode: parent,
168
+ prevNode: fg('platform_editor_drag_and_drop_target_v2') ? node : undefined,
169
+ parentNode: parent || undefined,
77
170
  formatMessage
78
- })));
171
+ }, -1, anchorHeightsCache));
79
172
  }
80
- prevNode = node;
81
- return depth < getNestedDepth();
173
+ if (fg('platform_editor_drag_and_drop_target_v2')) {
174
+ pushNodeStack(node, depth);
175
+ } else {
176
+ prevNode = node;
177
+ }
178
+ return depth < getNestedDepth() && shouldDescend(node);
82
179
  });
83
-
84
- //TODO: Should this use createDropTargetDecoration?
85
- decs.push(Decoration.widget(newState.doc.nodeSize - 2, (_, getPos) => {
86
- const element = document.createElement('div');
87
- element.setAttribute('data-blocks-drop-target-container', 'true');
88
- ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
89
- api,
90
- getPos,
91
- formatMessage
92
- }), element);
93
- return element;
94
- }, {
95
- type: 'drop-target-decoration'
96
- }));
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));
97
186
  return decs;
98
187
  };
99
188
  export const emptyParagraphNodeDecorations = () => {
@@ -11,6 +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
15
  import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
15
16
  import { dragHandleDecoration, dropTargetDecorations, emptyParagraphNodeDecorations, nodeDecorations } from './decorations';
16
17
  import { handleMouseOver } from './handle-mouse-over';
@@ -97,6 +98,10 @@ export const createPlugin = (api, getIntl) => {
97
98
  if (fg('platform_editor_element_dnd_nested_fix_patch_2')) {
98
99
  // TODO: Remove this once FG is used in code
99
100
  }
101
+ let anchorHeightsCache;
102
+ if (!isAnchorSupported() && fg('platform_editor_drag_and_drop_target_v2')) {
103
+ anchorHeightsCache = new AnchorHeightsCache();
104
+ }
100
105
  return new SafePlugin({
101
106
  key,
102
107
  state: {
@@ -244,7 +249,7 @@ export const createPlugin = (api, getIntl) => {
244
249
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
245
250
  if (shouldCreateDropTargets || isBlocksDragTargetDebug()) {
246
251
  var _meta$activeNode6;
247
- const decs = dropTargetDecorations(newState, api, formatMessage, isNestedEnabled ? (_meta$activeNode6 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode6 !== void 0 ? _meta$activeNode6 : mappedActiveNodePos : meta === null || meta === void 0 ? void 0 : meta.activeNode);
252
+ const decs = dropTargetDecorations(newState, api, formatMessage, isNestedEnabled ? (_meta$activeNode6 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode6 !== void 0 ? _meta$activeNode6 : mappedActiveNodePos : meta === null || meta === void 0 ? void 0 : meta.activeNode, anchorHeightsCache);
248
253
  decorations = decorations.add(newState.doc, decs);
249
254
  }
250
255
  }
@@ -319,6 +324,8 @@ export const createPlugin = (api, getIntl) => {
319
324
  return false;
320
325
  },
321
326
  dragstart(view) {
327
+ var _anchorHeightsCache;
328
+ (_anchorHeightsCache = anchorHeightsCache) === null || _anchorHeightsCache === void 0 ? void 0 : _anchorHeightsCache.setEditorView(view);
322
329
  view.dispatch(view.state.tr.setMeta(key, {
323
330
  isPMDragging: true
324
331
  }));
@@ -116,7 +116,7 @@ export const nodeMargins = {
116
116
  bottom: 0
117
117
  },
118
118
  codeBlock: {
119
- top: 0,
119
+ top: 12,
120
120
  bottom: 0
121
121
  },
122
122
  panel: {
@@ -124,8 +124,8 @@ export const nodeMargins = {
124
124
  bottom: 0
125
125
  },
126
126
  rule: {
127
- top: 20,
128
- bottom: 20
127
+ top: 24,
128
+ bottom: 24
129
129
  },
130
130
  mediaSingle: {
131
131
  top: 24,
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
+ import { Fragment, useEffect, useMemo, useRef, useState } from 'react';
6
+
7
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
8
+ import { css, jsx } from '@emotion/react';
9
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
10
+ import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
11
+ import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
12
+ import { layers } from '@atlaskit/theme/constants';
13
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
14
+ import { getNodeAnchor } from '../pm-plugins/decorations';
15
+ import { isAnchorSupported } from '../utils/anchor-utils';
16
+ import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
17
+ import { getNestedNodeLeftPaddingMargin } from './consts';
18
+ const DEFAULT_DROP_INDICATOR_WIDTH = 760;
19
+ const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH = '--editor-block-controls-drop-indicator-width';
20
+ const EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN = '--editor-block-controls-drop-target-leftMargin';
21
+ const EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX = '--editor-block-controls-drop-target-zindex';
22
+ export const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET = '--editor-block-controls-drop-indicator-offset';
23
+ export const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP = '--editor-block-controls-drop-indicator-gap';
24
+ const styleDropTarget = css({
25
+ marginLeft: `calc(-1 * var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN}, 0))`,
26
+ paddingLeft: `var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN}, 0)`,
27
+ position: 'absolute',
28
+ left: '0',
29
+ display: 'block',
30
+ zIndex: `var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX}, 110)`,
31
+ transform: `translateY(var(${EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET}, 0))`
32
+ });
33
+ const styleDropIndicator = css({
34
+ height: '100%',
35
+ margin: '0 auto',
36
+ position: 'relative',
37
+ width: `var(${EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH}, 100%)`
38
+ });
39
+ const nestedDropIndicatorStyle = css({
40
+ position: 'relative'
41
+ });
42
+ const dropZoneStyles = css({
43
+ margin: 0,
44
+ position: 'absolute',
45
+ width: '100%',
46
+ zIndex: 110,
47
+ minHeight: '4px'
48
+ });
49
+ const nestedDropZoneStyle = css({
50
+ left: '4px',
51
+ right: '4px',
52
+ width: 'unset'
53
+ });
54
+ const enableDropZone = ['paragraph', 'mediaSingle', 'heading', 'codeBlock', 'decisionList', 'bulletList', 'orderedList', 'taskList', 'extension', 'blockCard'];
55
+ const HoverZone = ({
56
+ onDragEnter,
57
+ onDragLeave,
58
+ onDrop,
59
+ node,
60
+ editorWidth,
61
+ anchorHeightsCache,
62
+ position,
63
+ isNestedDropTarget
64
+ }) => {
65
+ const ref = useRef(null);
66
+ useEffect(() => {
67
+ if (ref.current) {
68
+ return dropTargetForElements({
69
+ element: ref.current,
70
+ onDragEnter,
71
+ onDragLeave,
72
+ onDrop
73
+ });
74
+ }
75
+ }, [onDragEnter, onDragLeave, onDrop]);
76
+ const hoverZoneUpperStyle = useMemo(() => {
77
+ const anchorName = node ? getNodeAnchor(node) : '';
78
+ const heightStyleOffset = `var(--editor-block-controls-drop-indicator-gap, 0)/2`;
79
+ const transformOffset = `var(${EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET}, 0)`;
80
+ 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';
81
+ const transform = position === 'upper' ? `translateY(calc(-100% + ${transformOffset}))` : `translateY(${transformOffset})`;
82
+ return css({
83
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
84
+ height: heightStyle,
85
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
86
+ transform: transform,
87
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
88
+ maxWidth: `${editorWidth || 0}px`
89
+ });
90
+ }, [anchorHeightsCache, editorWidth, node, position]);
91
+ return jsx("div", {
92
+ ref: ref
93
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
94
+ ,
95
+ className: `drop-target-hover-zone-${position}`
96
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
97
+ ,
98
+ css: [dropZoneStyles, isNestedDropTarget && nestedDropZoneStyle, hoverZoneUpperStyle]
99
+ });
100
+ };
101
+ export const DropTargetV2 = ({
102
+ api,
103
+ getPos,
104
+ prevNode,
105
+ nextNode,
106
+ parentNode,
107
+ formatMessage,
108
+ anchorHeightsCache
109
+ }) => {
110
+ const [isDraggedOver, setIsDraggedOver] = useState(false);
111
+ const {
112
+ widthState
113
+ } = useSharedPluginState(api, ['width']);
114
+ const isNestedDropTarget = (parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) !== 'doc';
115
+ const onDrop = () => {
116
+ var _api$blockControls;
117
+ const {
118
+ activeNode
119
+ } = (api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {};
120
+ if (!activeNode) {
121
+ return;
122
+ }
123
+ const pos = getPos();
124
+ if (activeNode && pos !== undefined) {
125
+ var _api$core, _api$blockControls2, _api$blockControls2$c;
126
+ const {
127
+ pos: start
128
+ } = activeNode;
129
+ 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$c = _api$blockControls2.commands) === null || _api$blockControls2$c === void 0 ? void 0 : _api$blockControls2$c.moveNode(start, pos, undefined, formatMessage));
130
+ }
131
+ };
132
+ const dynamicStyle = {
133
+ width: isNestedDropTarget ? 'unset' : '100%',
134
+ [EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH]: isNestedDropTarget ? '100%' : `${(widthState === null || widthState === void 0 ? void 0 : widthState.lineLength) || DEFAULT_DROP_INDICATOR_WIDTH}px`,
135
+ [EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN]: isNestedDropTarget ? getNestedNodeLeftPaddingMargin(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0',
136
+ [EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX]: editorExperiment('nested-dnd', true) ? layers.navigation() : layers.card()
137
+ };
138
+ return jsx(Fragment, null, jsx(HoverZone, {
139
+ onDragEnter: () => setIsDraggedOver(true),
140
+ onDragLeave: () => setIsDraggedOver(false),
141
+ onDrop: onDrop,
142
+ node: prevNode,
143
+ editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
144
+ anchorHeightsCache: anchorHeightsCache,
145
+ position: "upper",
146
+ isNestedDropTarget: isNestedDropTarget
147
+ }), jsx("div", {
148
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
149
+ css: [styleDropTarget, isNestedDropTarget && nestedDropIndicatorStyle]
150
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
151
+ ,
152
+ style: dynamicStyle,
153
+ "data-testid": "block-ctrl-drop-target"
154
+ },
155
+ // 4px gap to clear expand node border
156
+ (isDraggedOver || isBlocksDragTargetDebug()) && jsx("div", {
157
+ css: styleDropIndicator,
158
+ "data-testid": "block-ctrl-drop-indicator"
159
+ }, jsx(DropIndicator, {
160
+ edge: "bottom"
161
+ }))), jsx(HoverZone, {
162
+ onDragEnter: () => setIsDraggedOver(true),
163
+ onDragLeave: () => setIsDraggedOver(false),
164
+ onDrop: onDrop,
165
+ node: nextNode,
166
+ editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
167
+ anchorHeightsCache: anchorHeightsCache,
168
+ position: "lower",
169
+ isNestedDropTarget: isNestedDropTarget
170
+ }));
171
+ };
@@ -0,0 +1,51 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import memoizeOne from 'memoize-one';
3
+ export const isAnchorSupported = memoizeOne(() => {
4
+ // directly use CSS would cause failed SSR tests.
5
+ if (window.CSS && window.CSS.supports) {
6
+ return window.CSS.supports('anchor-name: --a');
7
+ }
8
+ return false;
9
+ });
10
+ export class AnchorHeightsCache {
11
+ constructor() {
12
+ _defineProperty(this, "anchorHeightsMap", {});
13
+ _defineProperty(this, "isAnchorSupported", isAnchorSupported());
14
+ _defineProperty(this, "isDirty", true);
15
+ _defineProperty(this, "view", null);
16
+ }
17
+ clear() {
18
+ this.isDirty = true;
19
+ this.anchorHeightsMap = {};
20
+ }
21
+ getHeights() {
22
+ if (this.isDirty) {
23
+ var _this$view;
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) => {
26
+ const anchorName = curr.getAttribute('data-drag-handler-anchor-name');
27
+ if (anchorName) {
28
+ return {
29
+ ...prev,
30
+ [anchorName]: curr.clientHeight
31
+ };
32
+ }
33
+ return prev;
34
+ }, {});
35
+ this.isDirty = false;
36
+ }
37
+ return this.anchorHeightsMap;
38
+ }
39
+ setEditorView(view) {
40
+ if (this.view !== view) {
41
+ this.view = view;
42
+ }
43
+ }
44
+ getHeight(anchorName) {
45
+ if (this.isAnchorSupported) {
46
+ return null;
47
+ }
48
+ const heights = this.getHeights();
49
+ return heights[anchorName];
50
+ }
51
+ }
@@ -11,10 +11,10 @@ export const getNestedNodePosition = state => {
11
11
  if ($pos.depth < 1) {
12
12
  return nestedNodePos;
13
13
  }
14
- const parentNodeOfSpecificTypes = findParentNodeOfType([state.schema.nodes.bulletList, state.schema.nodes.orderedList, state.schema.nodes.blockquote, state.schema.nodes.taskList])(state.selection);
14
+ const parentNodeOfSpecificTypes = findParentNodeOfType([state.schema.nodes.bulletList, state.schema.nodes.orderedList, state.schema.nodes.blockquote, state.schema.nodes.taskList, state.schema.nodes.decisionList])(state.selection);
15
15
  if (parentNodeOfSpecificTypes) {
16
16
  const parentNodeType = parentNodeOfSpecificTypes.node.type.name;
17
- nestedNodePos = ['bulletList', 'orderedList'].includes(parentNodeType) ? $pos.before($pos.depth - 1) : ['blockquote', 'taskList'].includes(parentNodeType) ? $pos.before() : nestedNodePos;
17
+ nestedNodePos = ['bulletList', 'orderedList'].includes(parentNodeType) ? $pos.before($pos.depth - 1) : ['blockquote', 'taskList', 'decisionList'].includes(parentNodeType) ? $pos.before() : nestedNodePos;
18
18
  }
19
19
  } else {
20
20
  nestedNodePos = selection.$from.pos;
@@ -99,7 +99,9 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
99
99
  moveToPos = $pos.after($pos.depth) + 1;
100
100
  } else if (direction === DIRECTION.UP) {
101
101
  var nodeBefore = $pos.depth > 1 && nodeIndex === 0 && fg('platform_editor_element_dnd_nested_a11y') ? $pos.node($pos.depth) : $pos.nodeBefore;
102
- moveToPos = $pos.depth > 1 && nodeIndex === 0 && fg('platform_editor_element_dnd_nested_a11y') ? $pos.before($pos.depth) - 1 : nodeBefore ? currentNodePos - nodeBefore.nodeSize : moveToPos;
102
+ if (nodeBefore) {
103
+ moveToPos = currentNodePos - nodeBefore.nodeSize;
104
+ }
103
105
  } else {
104
106
  var endOfDoc = $pos.end();
105
107
  var nodeAfterPos = $pos.posAtIndex($pos.index() + 1);