@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.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/commands/move-node.js +3 -1
- package/dist/cjs/pm-plugins/decorations.js +127 -43
- package/dist/cjs/pm-plugins/main.js +8 -1
- package/dist/cjs/ui/consts.js +3 -3
- package/dist/cjs/ui/drop-target-v2.js +184 -0
- package/dist/cjs/utils/anchor-utils.js +70 -0
- package/dist/cjs/utils/getNestedNodePosition.js +2 -2
- package/dist/es2019/commands/move-node.js +3 -1
- package/dist/es2019/pm-plugins/decorations.js +122 -33
- package/dist/es2019/pm-plugins/main.js +8 -1
- package/dist/es2019/ui/consts.js +3 -3
- package/dist/es2019/ui/drop-target-v2.js +171 -0
- package/dist/es2019/utils/anchor-utils.js +51 -0
- package/dist/es2019/utils/getNestedNodePosition.js +2 -2
- package/dist/esm/commands/move-node.js +3 -1
- package/dist/esm/pm-plugins/decorations.js +126 -42
- package/dist/esm/pm-plugins/main.js +8 -1
- package/dist/esm/ui/consts.js +3 -3
- package/dist/esm/ui/drop-target-v2.js +176 -0
- package/dist/esm/utils/anchor-utils.js +63 -0
- package/dist/esm/utils/getNestedNodePosition.js +2 -2
- package/dist/types/pm-plugins/decorations.d.ts +6 -1
- package/dist/types/ui/drop-target-v2.d.ts +8 -0
- package/dist/types/utils/anchor-utils.d.ts +12 -0
- package/dist/types-ts4.5/pm-plugins/decorations.d.ts +6 -1
- package/dist/types-ts4.5/ui/drop-target-v2.d.ts +8 -0
- package/dist/types-ts4.5/utils/anchor-utils.d.ts +12 -0
- package/package.json +4 -1
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
166
|
+
decs.push(createDropTargetDecoration(endPos, {
|
|
74
167
|
api,
|
|
75
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
}));
|
package/dist/es2019/ui/consts.js
CHANGED
|
@@ -116,7 +116,7 @@ export const nodeMargins = {
|
|
|
116
116
|
bottom: 0
|
|
117
117
|
},
|
|
118
118
|
codeBlock: {
|
|
119
|
-
top:
|
|
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:
|
|
128
|
-
bottom:
|
|
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
|
-
|
|
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);
|