@atlaskit/editor-plugin-block-controls 3.0.0 → 3.1.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.
- package/CHANGELOG.md +21 -0
- package/dist/cjs/blockControlsPlugin.js +27 -14
- package/dist/cjs/editor-commands/move-node.js +15 -18
- package/dist/cjs/pm-plugins/decorations-common.js +2 -4
- package/dist/cjs/pm-plugins/main.js +73 -34
- package/dist/cjs/pm-plugins/utils/getSelection.js +1 -1
- package/dist/cjs/pm-plugins/utils/selection.js +34 -4
- package/dist/cjs/ui/consts.js +9 -1
- package/dist/cjs/ui/drag-handle.js +69 -36
- package/dist/es2019/blockControlsPlugin.js +27 -14
- package/dist/es2019/editor-commands/move-node.js +17 -20
- package/dist/es2019/pm-plugins/decorations-common.js +2 -4
- package/dist/es2019/pm-plugins/main.js +70 -23
- package/dist/es2019/pm-plugins/utils/getSelection.js +1 -1
- package/dist/es2019/pm-plugins/utils/selection.js +33 -3
- package/dist/es2019/ui/consts.js +8 -0
- package/dist/es2019/ui/drag-handle.js +59 -30
- package/dist/esm/blockControlsPlugin.js +27 -14
- package/dist/esm/editor-commands/move-node.js +16 -19
- package/dist/esm/pm-plugins/decorations-common.js +2 -4
- package/dist/esm/pm-plugins/main.js +71 -32
- package/dist/esm/pm-plugins/utils/getSelection.js +1 -1
- package/dist/esm/pm-plugins/utils/selection.js +33 -3
- package/dist/esm/ui/consts.js +8 -0
- package/dist/esm/ui/drag-handle.js +70 -37
- package/dist/types/blockControlsPluginType.d.ts +2 -0
- package/dist/types/pm-plugins/main.d.ts +2 -1
- package/dist/types/pm-plugins/utils/selection.d.ts +13 -1
- package/dist/types/ui/consts.d.ts +7 -0
- package/dist/types-ts4.5/blockControlsPluginType.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -1
- package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +13 -1
- package/dist/types-ts4.5/ui/consts.d.ts +7 -0
- package/package.json +4 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TextSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
1
2
|
import { key } from '../main';
|
|
2
3
|
export const getMultiSelectionIfPosInside = (api, pos, tr) => {
|
|
3
4
|
var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
|
|
@@ -10,7 +11,7 @@ export const getMultiSelectionIfPosInside = (api, pos, tr) => {
|
|
|
10
11
|
const multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
|
|
11
12
|
|
|
12
13
|
// We subtract one as the handle position is before the node
|
|
13
|
-
return pos >= multiFrom - 1 && pos
|
|
14
|
+
return pos >= multiFrom - 1 && pos < multiTo ? {
|
|
14
15
|
anchor: multiSelectDnD.anchor,
|
|
15
16
|
head: multiSelectDnD.head
|
|
16
17
|
} : {};
|
|
@@ -29,12 +30,41 @@ export const getSelectedSlicePosition = (handlePos, tr, api) => {
|
|
|
29
30
|
head
|
|
30
31
|
} = getMultiSelectionIfPosInside(api, handlePos, tr);
|
|
31
32
|
const inSelection = anchor !== undefined && head !== undefined;
|
|
32
|
-
const from = inSelection ? Math.min(anchor, head) : handlePos;
|
|
33
|
+
const from = inSelection ? Math.min(anchor || 0, head || 0) : handlePos;
|
|
33
34
|
const activeNode = tr.doc.nodeAt(handlePos);
|
|
34
35
|
const activeNodeEndPos = handlePos + ((_activeNode$nodeSize = activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeSize) !== null && _activeNode$nodeSize !== void 0 ? _activeNode$nodeSize : 1);
|
|
35
|
-
const to = inSelection ? Math.max(anchor, head) : activeNodeEndPos;
|
|
36
|
+
const to = inSelection ? Math.max(anchor || 0, head || 0) : activeNodeEndPos;
|
|
36
37
|
return {
|
|
37
38
|
from,
|
|
38
39
|
to
|
|
39
40
|
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Takes a position and expands the selection to encompass the node at that position. Ignores empty or out of range selections.
|
|
45
|
+
* Ignores positions that are in text blocks (i.e. not start of a node)
|
|
46
|
+
* @returns TextSelection if expanded, otherwise returns Selection that was passed in.
|
|
47
|
+
*/
|
|
48
|
+
export const expandSelectionHeadToNodeAtPos = (selection, nodePos) => {
|
|
49
|
+
const doc = selection.$anchor.doc;
|
|
50
|
+
if (nodePos < 0 || nodePos > doc.nodeSize - 2 || selection.empty) {
|
|
51
|
+
return selection;
|
|
52
|
+
}
|
|
53
|
+
const $pos = doc.resolve(nodePos);
|
|
54
|
+
const node = $pos.nodeAfter;
|
|
55
|
+
if ($pos.node().isTextblock || !node) {
|
|
56
|
+
return selection;
|
|
57
|
+
}
|
|
58
|
+
const $newHead = nodePos < selection.anchor ? $pos : doc.resolve(node.nodeSize + nodePos);
|
|
59
|
+
const textSelection = new TextSelection(selection.$anchor, $newHead);
|
|
60
|
+
return textSelection;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* This swaps the anchor/head for NodeSelections when its anchor > pos.
|
|
65
|
+
* This is because NodeSelection always has an anchor at the start of the node,
|
|
66
|
+
* which may not align with the existing selection.
|
|
67
|
+
*/
|
|
68
|
+
export const alignAnchorHeadInDirectionOfPos = (selection, pos) => {
|
|
69
|
+
return selection instanceof NodeSelection && Math.max(pos, selection.anchor) === selection.anchor ? new TextSelection(selection.$head, selection.$anchor) : selection;
|
|
40
70
|
};
|
package/dist/es2019/ui/consts.js
CHANGED
|
@@ -18,6 +18,14 @@ export const DRAG_HANDLE_H5_TOP_ADJUSTMENT = 3;
|
|
|
18
18
|
export const DRAG_HANDLE_H6_TOP_ADJUSTMENT = 3;
|
|
19
19
|
export const DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = 8;
|
|
20
20
|
export const DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = 2;
|
|
21
|
+
|
|
22
|
+
/** We only want to shift-select nodes that are at the top level of a document.
|
|
23
|
+
* This is because funky things happen when selecting inside of tableCells, but we
|
|
24
|
+
* also want to avoid heavily nested cases to descope potential corner cases.
|
|
25
|
+
* Various top level nodes have their selection 'from' at depths other than 0,
|
|
26
|
+
* so we allow for some leniency to capture them all. e.g. Table is depth 3.
|
|
27
|
+
*/
|
|
28
|
+
export const DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = 3;
|
|
21
29
|
const nodeTypeExcludeList = ['embedCard', 'mediaSingle', 'table'];
|
|
22
30
|
export const dragHandleGap = (nodeType, parentNodeType) => {
|
|
23
31
|
if (nodeType === 'layoutSection' && fg('platform_editor_advanced_layouts_post_fix_patch_2')) {
|
|
@@ -25,7 +25,8 @@ import { key } from '../pm-plugins/main';
|
|
|
25
25
|
import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
|
|
26
26
|
import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
|
|
27
27
|
import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
|
|
28
|
-
import {
|
|
28
|
+
import { alignAnchorHeadInDirectionOfPos, expandSelectionHeadToNodeAtPos } from '../pm-plugins/utils/selection';
|
|
29
|
+
import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, topPositionAdjustment } from './consts';
|
|
29
30
|
import { dragPreview } from './drag-preview';
|
|
30
31
|
const iconWrapperStyles = xcss({
|
|
31
32
|
display: 'flex',
|
|
@@ -61,6 +62,13 @@ const dragHandleButtonStyles = css({
|
|
|
61
62
|
},
|
|
62
63
|
'&:focus': {
|
|
63
64
|
outline: `2px solid ${"var(--ds-border-focused, #388BFF)"}`
|
|
65
|
+
},
|
|
66
|
+
'&:disabled': {
|
|
67
|
+
color: "var(--ds-icon-disabled, #8993A4)",
|
|
68
|
+
backgroundColor: 'transparent'
|
|
69
|
+
},
|
|
70
|
+
'&:hover:disabled': {
|
|
71
|
+
backgroundColor: "var(--ds-background-disabled, transparent)"
|
|
64
72
|
}
|
|
65
73
|
});
|
|
66
74
|
const dragHandleMultiLineSelectionFixFirefox = css({
|
|
@@ -116,15 +124,18 @@ export const DragHandle = ({
|
|
|
116
124
|
handleOptions,
|
|
117
125
|
isTopLevelNode = true
|
|
118
126
|
}) => {
|
|
119
|
-
var _api$core2, _api$analytics2, _api$core4;
|
|
127
|
+
var _api$core2, _api$analytics2, _api$blockControls3, _api$core4;
|
|
120
128
|
const start = getPos();
|
|
121
129
|
const buttonRef = useRef(null);
|
|
122
130
|
const [blockCardWidth, setBlockCardWidth] = useState(768);
|
|
123
131
|
const [dragHandleSelected, setDragHandleSelected] = useState(false);
|
|
132
|
+
const [dragHandleDisabled, setDragHandleDisabled] = useState(false);
|
|
124
133
|
const {
|
|
125
134
|
featureFlagsState
|
|
126
135
|
} = useSharedPluginState(api, ['featureFlags']);
|
|
127
136
|
const selection = useSharedPluginStateSelector(api, 'selection.selection');
|
|
137
|
+
const isShiftDown = useSharedPluginStateSelector(api, 'blockControls.isShiftDown');
|
|
138
|
+
const multiSelectDnD = useSharedPluginStateSelector(api, 'blockControls.multiSelectDnD');
|
|
128
139
|
const isLayoutColumn = nodeType === 'layoutColumn';
|
|
129
140
|
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
130
141
|
exposure: true
|
|
@@ -144,9 +155,11 @@ export const DragHandle = ({
|
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
157
|
}, [anchorName, nodeType, view.dom]);
|
|
147
|
-
const handleOnClick = useCallback(
|
|
158
|
+
const handleOnClick = useCallback(e => {
|
|
148
159
|
var _api$core;
|
|
149
|
-
|
|
160
|
+
if (!isMultiSelect) {
|
|
161
|
+
setDragHandleSelected(!dragHandleSelected);
|
|
162
|
+
}
|
|
150
163
|
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
151
164
|
tr
|
|
152
165
|
}) => {
|
|
@@ -155,7 +168,24 @@ export const DragHandle = ({
|
|
|
155
168
|
if (startPos === undefined) {
|
|
156
169
|
return tr;
|
|
157
170
|
}
|
|
158
|
-
|
|
171
|
+
const $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? tr.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : tr.selection.$anchor;
|
|
172
|
+
if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
|
|
173
|
+
tr = selectNode(tr, startPos, nodeType);
|
|
174
|
+
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
175
|
+
var _api$blockControls;
|
|
176
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.commands.toggleBlockMenu()({
|
|
177
|
+
tr
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
|
|
181
|
+
var _api$blockControls2;
|
|
182
|
+
const alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
|
|
183
|
+
const selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
|
|
184
|
+
tr.setSelection(selectionWithExpandedHead);
|
|
185
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.setMultiSelectPositions()({
|
|
186
|
+
tr
|
|
187
|
+
});
|
|
188
|
+
}
|
|
159
189
|
const resolvedMovingNode = tr.doc.resolve(startPos);
|
|
160
190
|
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
161
191
|
tr.setMeta('scrollIntoView', false);
|
|
@@ -172,14 +202,7 @@ export const DragHandle = ({
|
|
|
172
202
|
return tr;
|
|
173
203
|
});
|
|
174
204
|
view.focus();
|
|
175
|
-
|
|
176
|
-
const startPos = getPos();
|
|
177
|
-
if (startPos === undefined) {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(api.blockControls.commands.toggleBlockMenu());
|
|
181
|
-
}
|
|
182
|
-
}, [dragHandleSelected, api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 ? void 0 : api.blockControls.commands, view, getPos, nodeType]);
|
|
205
|
+
}, [isMultiSelect, api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, view, dragHandleSelected, getPos, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, isTopLevelNode, nodeType]);
|
|
183
206
|
|
|
184
207
|
// TODO - This needs to be investigated further. Drag preview generation is not always working
|
|
185
208
|
// as expected with a node selection. This workaround sets the selection to the node on mouseDown,
|
|
@@ -199,7 +222,6 @@ export const DragHandle = ({
|
|
|
199
222
|
const handleKeyDown = useCallback(e => {
|
|
200
223
|
if (fg('platform_editor_element_drag_and_drop_ed_23873')) {
|
|
201
224
|
// allow user to use spacebar to select the node
|
|
202
|
-
|
|
203
225
|
if (!e.repeat && e.key === ' ') {
|
|
204
226
|
var _api$core3;
|
|
205
227
|
const startPos = getPos();
|
|
@@ -216,9 +238,9 @@ export const DragHandle = ({
|
|
|
216
238
|
const $startPos = tr.doc.resolve(startPos + node.nodeSize);
|
|
217
239
|
const selection = new TextSelection($startPos);
|
|
218
240
|
tr.setSelection(selection);
|
|
219
|
-
tr.setMeta(key, {
|
|
241
|
+
!isMultiSelect && tr.setMeta(key, {
|
|
220
242
|
pos: startPos
|
|
221
|
-
});
|
|
243
|
+
});
|
|
222
244
|
return tr;
|
|
223
245
|
});
|
|
224
246
|
} else if (![e.altKey, e.ctrlKey, e.shiftKey].some(pressed => pressed)) {
|
|
@@ -227,7 +249,7 @@ export const DragHandle = ({
|
|
|
227
249
|
view.focus();
|
|
228
250
|
}
|
|
229
251
|
}
|
|
230
|
-
}, [getPos, api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, view]);
|
|
252
|
+
}, [getPos, api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, isMultiSelect, view]);
|
|
231
253
|
useEffect(() => {
|
|
232
254
|
const element = buttonRef.current;
|
|
233
255
|
if (!element) {
|
|
@@ -242,7 +264,6 @@ export const DragHandle = ({
|
|
|
242
264
|
onGenerateDragPreview: ({
|
|
243
265
|
nativeSetDragImage
|
|
244
266
|
}) => {
|
|
245
|
-
var _api$blockControls2;
|
|
246
267
|
if (isMultiSelect) {
|
|
247
268
|
var _api$core5;
|
|
248
269
|
api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.execute(({
|
|
@@ -253,8 +274,8 @@ export const DragHandle = ({
|
|
|
253
274
|
return tr;
|
|
254
275
|
}
|
|
255
276
|
if (!tr.selection.empty && handlePos >= tr.selection.$from.start() - 1 && handlePos <= tr.selection.to) {
|
|
256
|
-
var _api$
|
|
257
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
277
|
+
var _api$blockControls4;
|
|
278
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 ? void 0 : _api$blockControls4.commands.setMultiSelectPositions()({
|
|
258
279
|
tr
|
|
259
280
|
});
|
|
260
281
|
}
|
|
@@ -267,9 +288,6 @@ export const DragHandle = ({
|
|
|
267
288
|
doc,
|
|
268
289
|
selection
|
|
269
290
|
} = state;
|
|
270
|
-
const {
|
|
271
|
-
multiSelectDnD
|
|
272
|
-
} = (api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.sharedState.currentState()) || {};
|
|
273
291
|
let sliceFrom = selection.from;
|
|
274
292
|
let sliceTo = selection.to;
|
|
275
293
|
if (multiSelectDnD) {
|
|
@@ -281,7 +299,7 @@ export const DragHandle = ({
|
|
|
281
299
|
sliceTo = Math.max(anchor, head);
|
|
282
300
|
}
|
|
283
301
|
const expandedSlice = doc.slice(sliceFrom, sliceTo);
|
|
284
|
-
const isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos
|
|
302
|
+
const isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos < sliceTo && expandedSlice.content.childCount > 1;
|
|
285
303
|
setCustomNativeDragPreview({
|
|
286
304
|
getOffset: () => {
|
|
287
305
|
if (!isDraggingMultiLine) {
|
|
@@ -369,11 +387,10 @@ export const DragHandle = ({
|
|
|
369
387
|
api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions.execute(({
|
|
370
388
|
tr
|
|
371
389
|
}) => {
|
|
372
|
-
var
|
|
390
|
+
var _api$blockControls5, _api$analytics3;
|
|
373
391
|
let nodeTypes, hasSelectedMultipleNodes;
|
|
374
392
|
const resolvedMovingNode = tr.doc.resolve(start);
|
|
375
393
|
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
376
|
-
const multiSelectDnD = (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
|
|
377
394
|
if (multiSelectDnD) {
|
|
378
395
|
const attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
|
|
379
396
|
nodeTypes = attributes.nodeTypes;
|
|
@@ -382,7 +399,7 @@ export const DragHandle = ({
|
|
|
382
399
|
nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
|
|
383
400
|
hasSelectedMultipleNodes = false;
|
|
384
401
|
}
|
|
385
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
402
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 ? void 0 : _api$blockControls5.commands.setNodeDragged(getPos, anchorName, nodeType)({
|
|
386
403
|
tr
|
|
387
404
|
});
|
|
388
405
|
tr.setMeta('scrollIntoView', false);
|
|
@@ -405,7 +422,7 @@ export const DragHandle = ({
|
|
|
405
422
|
view.focus();
|
|
406
423
|
}
|
|
407
424
|
});
|
|
408
|
-
}, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
|
|
425
|
+
}, [anchorName, api, getPos, isMultiSelect, multiSelectDnD, nodeType, start, view]);
|
|
409
426
|
const macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
|
|
410
427
|
const calculatePosition = useCallback(() => {
|
|
411
428
|
let parentNodeType;
|
|
@@ -492,6 +509,17 @@ export const DragHandle = ({
|
|
|
492
509
|
}
|
|
493
510
|
setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
|
|
494
511
|
}, [start, selection, view.state, isMultiSelect]);
|
|
512
|
+
useEffect(() => {
|
|
513
|
+
if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
const $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? view.state.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : view.state.selection.$anchor;
|
|
517
|
+
if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
|
|
518
|
+
setDragHandleDisabled(true);
|
|
519
|
+
} else {
|
|
520
|
+
setDragHandleDisabled(false);
|
|
521
|
+
}
|
|
522
|
+
}, [isMultiSelect, isShiftDown, isTopLevelNode, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, view.state.doc, view.state.selection]);
|
|
495
523
|
let helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
|
|
496
524
|
description: formatMessage(blockControlsMessages.dragToMove)
|
|
497
525
|
}, {
|
|
@@ -578,6 +606,7 @@ export const DragHandle = ({
|
|
|
578
606
|
// eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
|
|
579
607
|
,
|
|
580
608
|
onDrop: handleOnDrop,
|
|
609
|
+
disabled: dragHandleDisabled,
|
|
581
610
|
"data-testid": "block-ctrl-drag-handle"
|
|
582
611
|
}, jsx(Box, {
|
|
583
612
|
as: "span",
|
|
@@ -585,11 +614,11 @@ export const DragHandle = ({
|
|
|
585
614
|
// eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
|
|
586
615
|
,
|
|
587
616
|
onDragStart: handleIconDragStart
|
|
588
|
-
},
|
|
617
|
+
}, jsx(DragHandlerIcon, {
|
|
589
618
|
label: "",
|
|
590
619
|
size: "medium"
|
|
591
620
|
})));
|
|
592
|
-
return fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
|
|
621
|
+
return !dragHandleDisabled && fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
|
|
593
622
|
content: jsx(TooltipContentWithMultipleShortcuts, {
|
|
594
623
|
helpDescriptors: helpDescriptors
|
|
595
624
|
}),
|
|
@@ -8,6 +8,7 @@ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
|
8
8
|
import { moveNode } from './editor-commands/move-node';
|
|
9
9
|
import { moveToLayout } from './editor-commands/move-to-layout';
|
|
10
10
|
import { createPlugin, key } from './pm-plugins/main';
|
|
11
|
+
import { selectNode } from './pm-plugins/utils/getSelection';
|
|
11
12
|
import BlockMenu from './ui/block-menu';
|
|
12
13
|
import { DragHandleMenu } from './ui/drag-handle-menu';
|
|
13
14
|
import { GlobalStylesWrapper } from './ui/global-styles';
|
|
@@ -81,29 +82,40 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
|
81
82
|
},
|
|
82
83
|
setMultiSelectPositions: function setMultiSelectPositions(anchor, head) {
|
|
83
84
|
return function (_ref6) {
|
|
84
|
-
var _api$selection;
|
|
85
|
+
var _api$selection, _$to$nodeBefore, _$from$nodeAfter;
|
|
85
86
|
var tr = _ref6.tr;
|
|
86
87
|
var _tr$selection = tr.selection,
|
|
87
88
|
userAnchor = _tr$selection.anchor,
|
|
88
89
|
userHead = _tr$selection.head;
|
|
89
|
-
var expandedAnchor, expandedHead;
|
|
90
|
+
var $expandedAnchor, $expandedHead;
|
|
90
91
|
if (anchor !== undefined && head !== undefined) {
|
|
91
|
-
expandedAnchor = tr.doc.resolve(anchor);
|
|
92
|
-
expandedHead = tr.doc.resolve(head);
|
|
92
|
+
$expandedAnchor = tr.doc.resolve(anchor);
|
|
93
|
+
$expandedHead = tr.doc.resolve(head);
|
|
93
94
|
} else {
|
|
94
95
|
var expandedSelection = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head);
|
|
95
|
-
expandedAnchor = expandedSelection.$anchor;
|
|
96
|
-
expandedHead = expandedSelection.$head;
|
|
96
|
+
$expandedAnchor = expandedSelection.$anchor;
|
|
97
|
+
$expandedHead = expandedSelection.$head;
|
|
97
98
|
}
|
|
98
|
-
api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.setManualSelection(expandedAnchor.pos, expandedHead.pos)({
|
|
99
|
+
api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.setManualSelection($expandedAnchor.pos, $expandedHead.pos)({
|
|
99
100
|
tr: tr
|
|
100
101
|
});
|
|
101
|
-
|
|
102
|
-
var
|
|
103
|
-
|
|
102
|
+
var $from = $expandedAnchor.min($expandedHead);
|
|
103
|
+
var $to = $expandedAnchor.max($expandedHead);
|
|
104
|
+
var expandedNormalisedSel;
|
|
105
|
+
if ($from.nodeAfter === $to.nodeBefore) {
|
|
106
|
+
selectNode(tr, $from.pos, $expandedAnchor.node().type.name);
|
|
107
|
+
expandedNormalisedSel = tr.selection;
|
|
108
|
+
} else if (((_$to$nodeBefore = $to.nodeBefore) === null || _$to$nodeBefore === void 0 ? void 0 : _$to$nodeBefore.type.name) === 'mediaSingle' || ((_$from$nodeAfter = $from.nodeAfter) === null || _$from$nodeAfter === void 0 ? void 0 : _$from$nodeAfter.type.name) === 'mediaSingle') {
|
|
109
|
+
expandedNormalisedSel = new TextSelection($expandedAnchor, $expandedHead);
|
|
110
|
+
tr.setSelection(expandedNormalisedSel);
|
|
111
|
+
} else {
|
|
112
|
+
// this is to normalise the selection's boundaries to inline positions, preventing it from collapsing
|
|
113
|
+
expandedNormalisedSel = TextSelection.between($expandedAnchor, $expandedHead);
|
|
114
|
+
tr.setSelection(expandedNormalisedSel);
|
|
115
|
+
}
|
|
104
116
|
var multiSelectDnD = {
|
|
105
|
-
anchor: expandedAnchor.pos,
|
|
106
|
-
head: expandedHead.pos,
|
|
117
|
+
anchor: $expandedAnchor.pos,
|
|
118
|
+
head: $expandedHead.pos,
|
|
107
119
|
textAnchor: expandedNormalisedSel.anchor,
|
|
108
120
|
textHead: expandedNormalisedSel.head,
|
|
109
121
|
userAnchor: userAnchor,
|
|
@@ -118,7 +130,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
|
118
130
|
}
|
|
119
131
|
},
|
|
120
132
|
getSharedState: function getSharedState(editorState) {
|
|
121
|
-
var _key$getState$isMenuO, _key$getState, _key$getState$activeN, _key$getState2, _key$getState$isDragg, _key$getState3, _key$getState$isPMDra, _key$getState4, _key$getState$multiSe, _key$getState5;
|
|
133
|
+
var _key$getState$isMenuO, _key$getState, _key$getState$activeN, _key$getState2, _key$getState$isDragg, _key$getState3, _key$getState$isPMDra, _key$getState4, _key$getState$multiSe, _key$getState5, _key$getState$isShift, _key$getState6;
|
|
122
134
|
if (!editorState) {
|
|
123
135
|
return undefined;
|
|
124
136
|
}
|
|
@@ -127,7 +139,8 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
|
127
139
|
activeNode: (_key$getState$activeN = (_key$getState2 = key.getState(editorState)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.activeNode) !== null && _key$getState$activeN !== void 0 ? _key$getState$activeN : undefined,
|
|
128
140
|
isDragging: (_key$getState$isDragg = (_key$getState3 = key.getState(editorState)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
|
|
129
141
|
isPMDragging: (_key$getState$isPMDra = (_key$getState4 = key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
|
|
130
|
-
multiSelectDnD: (_key$getState$multiSe = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined
|
|
142
|
+
multiSelectDnD: (_key$getState$multiSe = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
|
|
143
|
+
isShiftDown: (_key$getState$isShift = (_key$getState6 = key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined
|
|
131
144
|
};
|
|
132
145
|
},
|
|
133
146
|
contentComponent: function contentComponent(_ref7) {
|
|
@@ -4,7 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
4
4
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
5
5
|
import { expandedState } from '@atlaskit/editor-common/expand';
|
|
6
6
|
import { blockControlsMessages } from '@atlaskit/editor-common/messages';
|
|
7
|
-
import {
|
|
7
|
+
import { expandSelectionBounds, GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
8
8
|
import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
|
|
9
9
|
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
|
|
10
10
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
@@ -54,16 +54,14 @@ var isDragLayoutColumnToTopLevel = function isDragLayoutColumnToTopLevel($from,
|
|
|
54
54
|
* @returns the start position of a node if the node can be moved, otherwise -1
|
|
55
55
|
*/
|
|
56
56
|
var getCurrentNodePos = function getCurrentNodePos(state) {
|
|
57
|
-
var _activeNode$handleOpt;
|
|
58
57
|
var selection = state.selection;
|
|
59
|
-
var _ref = key.getState(state) || {},
|
|
60
|
-
activeNode = _ref.activeNode;
|
|
61
58
|
var currentNodePos = -1;
|
|
62
59
|
|
|
63
60
|
// There are 3 cases when a node can be moved
|
|
64
|
-
|
|
61
|
+
var focusedHandle = getFocusedHandle(state);
|
|
62
|
+
if (focusedHandle) {
|
|
65
63
|
// 1. drag handle of the node is focused
|
|
66
|
-
currentNodePos =
|
|
64
|
+
currentNodePos = focusedHandle.pos;
|
|
67
65
|
} else if (isInTable(state)) {
|
|
68
66
|
if (isTableSelected(selection)) {
|
|
69
67
|
var _findTable$pos, _findTable;
|
|
@@ -81,6 +79,12 @@ var getCurrentNodePos = function getCurrentNodePos(state) {
|
|
|
81
79
|
}
|
|
82
80
|
return currentNodePos;
|
|
83
81
|
};
|
|
82
|
+
var getFocusedHandle = function getFocusedHandle(state) {
|
|
83
|
+
var _activeNode$handleOpt;
|
|
84
|
+
var _ref = key.getState(state) || {},
|
|
85
|
+
activeNode = _ref.activeNode;
|
|
86
|
+
return activeNode && (_activeNode$handleOpt = activeNode.handleOptions) !== null && _activeNode$handleOpt !== void 0 && _activeNode$handleOpt.isFocused ? activeNode : undefined;
|
|
87
|
+
};
|
|
84
88
|
export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, formatMessage) {
|
|
85
89
|
return function (state) {
|
|
86
90
|
var isParentNodeOfTypeLayout;
|
|
@@ -90,20 +94,14 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
|
|
|
90
94
|
isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
|
|
91
95
|
}
|
|
92
96
|
var isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
93
|
-
var
|
|
94
|
-
var
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
expandedHead = pluginState.multiSelectDnD.head;
|
|
98
|
-
} else {
|
|
99
|
-
var expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
|
|
100
|
-
expandedAnchor = expandedSelection.$anchor.pos;
|
|
101
|
-
expandedHead = expandedSelection.$head.pos;
|
|
102
|
-
}
|
|
103
|
-
var currentNodePos = isMultiSelectEnabled ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
|
|
97
|
+
var expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
|
|
98
|
+
var expandedAnchor = expandedSelection.$anchor.pos;
|
|
99
|
+
var expandedHead = expandedSelection.$head.pos;
|
|
100
|
+
var currentNodePos = isMultiSelectEnabled && !getFocusedHandle(state) ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
|
|
104
101
|
if (currentNodePos > -1) {
|
|
105
102
|
var _state$doc$nodeAt;
|
|
106
103
|
var $pos = state.doc.resolve(currentNodePos);
|
|
104
|
+
var nodeAfterPos = isMultiSelectEnabled && !getFocusedHandle(state) ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
|
|
107
105
|
var isTopLevelNode = $pos.depth === 0;
|
|
108
106
|
var moveToPos = -1;
|
|
109
107
|
var nodeIndex = $pos.index();
|
|
@@ -211,7 +209,6 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
|
|
|
211
209
|
}
|
|
212
210
|
} else {
|
|
213
211
|
var _endOfDoc = $pos.end();
|
|
214
|
-
var nodeAfterPos = isMultiSelectEnabled ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
|
|
215
212
|
if (nodeAfterPos > _endOfDoc) {
|
|
216
213
|
return false;
|
|
217
214
|
}
|
|
@@ -290,8 +287,8 @@ export var moveNode = function moveNode(api) {
|
|
|
290
287
|
var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
291
288
|
exposure: true
|
|
292
289
|
});
|
|
290
|
+
var slicePosition = getSelectedSlicePosition(start, tr, api);
|
|
293
291
|
if (isMultiSelect) {
|
|
294
|
-
var slicePosition = getSelectedSlicePosition(start, tr, api);
|
|
295
292
|
sliceFrom = slicePosition.from;
|
|
296
293
|
sliceTo = slicePosition.to;
|
|
297
294
|
var attributes = getMultiSelectAnalyticsAttributes(tr, sliceFrom, sliceTo);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
3
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
import ReactDOM from 'react-dom';
|
|
4
5
|
import uuid from 'uuid';
|
|
5
6
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
6
7
|
export var TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
|
|
@@ -39,9 +40,6 @@ export var unmountDecorations = function unmountDecorations(nodeViewPortalProvid
|
|
|
39
40
|
// as it was more responsive and causes less re-rendering
|
|
40
41
|
var decorationsToRemove = document.querySelectorAll("[".concat(selector, "=\"true\"]"));
|
|
41
42
|
decorationsToRemove.forEach(function (el) {
|
|
42
|
-
|
|
43
|
-
if (nodeKey) {
|
|
44
|
-
nodeViewPortalProviderAPI.remove(nodeKey);
|
|
45
|
-
}
|
|
43
|
+
ReactDOM.unmountComponentAtNode(el);
|
|
46
44
|
});
|
|
47
45
|
};
|