@atlaskit/editor-plugin-block-controls 2.27.0 → 2.27.4
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 +39 -0
- package/dist/cjs/blockControlsPlugin.js +35 -6
- package/dist/cjs/pm-plugins/decorations-drop-target.js +11 -5
- package/dist/cjs/pm-plugins/main.js +2 -1
- package/dist/cjs/pm-plugins/utils/getSelection.js +2 -2
- package/dist/cjs/pm-plugins/utils/validation.js +2 -1
- package/dist/cjs/ui/block-menu-items.js +103 -0
- package/dist/cjs/ui/block-menu.js +77 -0
- package/dist/cjs/ui/consts.js +101 -2
- package/dist/cjs/ui/drag-handle.js +147 -41
- package/dist/cjs/ui/drag-preview.js +83 -34
- package/dist/es2019/blockControlsPlugin.js +34 -3
- package/dist/es2019/pm-plugins/decorations-drop-target.js +12 -5
- package/dist/es2019/pm-plugins/main.js +2 -1
- package/dist/es2019/pm-plugins/utils/getSelection.js +1 -1
- package/dist/es2019/pm-plugins/utils/validation.js +2 -1
- package/dist/es2019/ui/block-menu-items.js +92 -0
- package/dist/es2019/ui/block-menu.js +75 -0
- package/dist/es2019/ui/consts.js +100 -1
- package/dist/es2019/ui/drag-handle.js +152 -40
- package/dist/es2019/ui/drag-preview.js +83 -34
- package/dist/esm/blockControlsPlugin.js +35 -6
- package/dist/esm/pm-plugins/decorations-drop-target.js +11 -5
- package/dist/esm/pm-plugins/main.js +2 -1
- package/dist/esm/pm-plugins/utils/getSelection.js +1 -1
- package/dist/esm/pm-plugins/utils/validation.js +2 -1
- package/dist/esm/ui/block-menu-items.js +92 -0
- package/dist/esm/ui/block-menu.js +70 -0
- package/dist/esm/ui/consts.js +100 -1
- package/dist/esm/ui/drag-handle.js +149 -43
- package/dist/esm/ui/drag-preview.js +82 -34
- package/dist/types/blockControlsPluginType.d.ts +3 -0
- package/dist/types/pm-plugins/utils/getSelection.d.ts +3 -3
- package/dist/types/pm-plugins/utils/validation.d.ts +1 -1
- package/dist/types/ui/block-menu-items.d.ts +17 -0
- package/dist/types/ui/block-menu.d.ts +16 -0
- package/dist/types/ui/consts.d.ts +7 -0
- package/dist/types/ui/drag-preview.d.ts +9 -1
- package/dist/types-ts4.5/blockControlsPluginType.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/utils/getSelection.d.ts +3 -3
- package/dist/types-ts4.5/pm-plugins/utils/validation.d.ts +1 -1
- package/dist/types-ts4.5/ui/block-menu-items.d.ts +17 -0
- package/dist/types-ts4.5/ui/block-menu.d.ts +16 -0
- package/dist/types-ts4.5/ui/consts.d.ts +7 -0
- package/dist/types-ts4.5/ui/drag-preview.d.ts +9 -1
- package/package.json +5 -5
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { injectIntl } from 'react-intl-next';
|
|
3
|
+
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
4
|
+
import { Popup } from '@atlaskit/editor-common/ui';
|
|
5
|
+
import { ArrowKeyNavigationType, DropdownMenu } from '@atlaskit/editor-common/ui-menu';
|
|
6
|
+
import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
|
|
7
|
+
import { getBlockMenuItems, menuItemsCallback } from './block-menu-items';
|
|
8
|
+
import { BLOCK_MENU_WIDTH } from './consts';
|
|
9
|
+
const dragHandleSelector = '[data-blocks-drag-handle-container="true"] button';
|
|
10
|
+
const BlockMenu = ({
|
|
11
|
+
editorView,
|
|
12
|
+
mountPoint,
|
|
13
|
+
boundariesElement,
|
|
14
|
+
scrollableElement,
|
|
15
|
+
api,
|
|
16
|
+
intl: {
|
|
17
|
+
formatMessage
|
|
18
|
+
}
|
|
19
|
+
}) => {
|
|
20
|
+
const {
|
|
21
|
+
blockControlsState
|
|
22
|
+
} = useSharedPluginState(api, ['blockControls']);
|
|
23
|
+
if (!(blockControlsState !== null && blockControlsState !== void 0 && blockControlsState.isMenuOpen)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const targetHandleRef = document.querySelector(dragHandleSelector);
|
|
27
|
+
const items = getBlockMenuItems(formatMessage);
|
|
28
|
+
const handleOpenChange = payload => {
|
|
29
|
+
if (!(payload !== null && payload !== void 0 && payload.isOpen)) {
|
|
30
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.toggleBlockMenu({
|
|
31
|
+
closeMenu: true
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const onMenuItemActivated = ({
|
|
36
|
+
item
|
|
37
|
+
}) => {
|
|
38
|
+
if (editorView) {
|
|
39
|
+
var _menuItemsCallback, _menuItemsCallback$ca;
|
|
40
|
+
(_menuItemsCallback = menuItemsCallback[item.value.name]) === null || _menuItemsCallback === void 0 ? void 0 : (_menuItemsCallback$ca = _menuItemsCallback.call(menuItemsCallback, api, formatMessage)) === null || _menuItemsCallback$ca === void 0 ? void 0 : _menuItemsCallback$ca(editorView.state, editorView.dispatch, editorView);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
return /*#__PURE__*/React.createElement(Popup, {
|
|
44
|
+
alignX: 'right',
|
|
45
|
+
alignY: 'start'
|
|
46
|
+
// Ignored via go/ees005
|
|
47
|
+
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
48
|
+
,
|
|
49
|
+
target: targetHandleRef,
|
|
50
|
+
mountTo: undefined,
|
|
51
|
+
zIndex: akEditorFloatingOverlapPanelZIndex,
|
|
52
|
+
forcePlacement: true,
|
|
53
|
+
stick: true,
|
|
54
|
+
offset: [-18, 8]
|
|
55
|
+
}, /*#__PURE__*/React.createElement(DropdownMenu, {
|
|
56
|
+
mountTo: mountPoint,
|
|
57
|
+
boundariesElement: boundariesElement,
|
|
58
|
+
scrollableElement: scrollableElement
|
|
59
|
+
//This needs be removed when the a11y is completely handled
|
|
60
|
+
//Disabling key navigation now as it works only partially
|
|
61
|
+
,
|
|
62
|
+
arrowKeyNavigationProviderOptions: {
|
|
63
|
+
type: ArrowKeyNavigationType.MENU
|
|
64
|
+
},
|
|
65
|
+
items: items,
|
|
66
|
+
isOpen: true,
|
|
67
|
+
fitWidth: BLOCK_MENU_WIDTH,
|
|
68
|
+
section: {
|
|
69
|
+
hasSeparator: true
|
|
70
|
+
},
|
|
71
|
+
onOpenChange: handleOpenChange,
|
|
72
|
+
onItemActivated: onMenuItemActivated
|
|
73
|
+
}));
|
|
74
|
+
};
|
|
75
|
+
export default injectIntl(BlockMenu);
|
package/dist/es2019/ui/consts.js
CHANGED
|
@@ -120,6 +120,104 @@ Array.from({
|
|
|
120
120
|
}, 1000);
|
|
121
121
|
return [currKeyValue, dropTargetMarginMap[value]];
|
|
122
122
|
}));
|
|
123
|
+
export const spacingBetweenNodesForPreview = {
|
|
124
|
+
paragraph: {
|
|
125
|
+
top: '0.75rem',
|
|
126
|
+
bottom: '0'
|
|
127
|
+
},
|
|
128
|
+
heading1: {
|
|
129
|
+
top: '1.45833em',
|
|
130
|
+
bottom: '0'
|
|
131
|
+
},
|
|
132
|
+
heading2: {
|
|
133
|
+
top: '1.4em',
|
|
134
|
+
bottom: '0'
|
|
135
|
+
},
|
|
136
|
+
heading3: {
|
|
137
|
+
top: '1.31249em',
|
|
138
|
+
bottom: '0'
|
|
139
|
+
},
|
|
140
|
+
heading4: {
|
|
141
|
+
top: '1.25em',
|
|
142
|
+
bottom: '0'
|
|
143
|
+
},
|
|
144
|
+
heading5: {
|
|
145
|
+
top: '1.45833em',
|
|
146
|
+
bottom: '0'
|
|
147
|
+
},
|
|
148
|
+
heading6: {
|
|
149
|
+
top: '1.59091em',
|
|
150
|
+
bottom: '0'
|
|
151
|
+
},
|
|
152
|
+
table: {
|
|
153
|
+
top: '0',
|
|
154
|
+
bottom: '0'
|
|
155
|
+
},
|
|
156
|
+
bulletList: {
|
|
157
|
+
top: '10px',
|
|
158
|
+
bottom: '0'
|
|
159
|
+
},
|
|
160
|
+
orderedList: {
|
|
161
|
+
top: '10px',
|
|
162
|
+
bottom: '0'
|
|
163
|
+
},
|
|
164
|
+
decisionList: {
|
|
165
|
+
top: '0.5rem',
|
|
166
|
+
bottom: '0'
|
|
167
|
+
},
|
|
168
|
+
taskList: {
|
|
169
|
+
top: '0.75rem',
|
|
170
|
+
bottom: '0'
|
|
171
|
+
},
|
|
172
|
+
codeBlock: {
|
|
173
|
+
top: '0.75rem',
|
|
174
|
+
bottom: '0'
|
|
175
|
+
},
|
|
176
|
+
panel: {
|
|
177
|
+
top: '0.75rem',
|
|
178
|
+
bottom: '0'
|
|
179
|
+
},
|
|
180
|
+
rule: {
|
|
181
|
+
top: '1.5rem',
|
|
182
|
+
bottom: '1.5rem'
|
|
183
|
+
},
|
|
184
|
+
mediaSingle: {
|
|
185
|
+
top: '24px',
|
|
186
|
+
bottom: '24px'
|
|
187
|
+
},
|
|
188
|
+
media: {
|
|
189
|
+
top: '24px',
|
|
190
|
+
bottom: '24px'
|
|
191
|
+
},
|
|
192
|
+
bodiedExtension: {
|
|
193
|
+
top: '0',
|
|
194
|
+
bottom: '0'
|
|
195
|
+
},
|
|
196
|
+
extension: {
|
|
197
|
+
top: '0',
|
|
198
|
+
bottom: '0'
|
|
199
|
+
},
|
|
200
|
+
layoutSection: {
|
|
201
|
+
top: '0',
|
|
202
|
+
bottom: '0'
|
|
203
|
+
},
|
|
204
|
+
blockquote: {
|
|
205
|
+
top: '0',
|
|
206
|
+
bottom: '0'
|
|
207
|
+
},
|
|
208
|
+
embedCard: {
|
|
209
|
+
top: '24px',
|
|
210
|
+
bottom: '24px'
|
|
211
|
+
},
|
|
212
|
+
blockCard: {
|
|
213
|
+
top: '0.75rem',
|
|
214
|
+
bottom: '0'
|
|
215
|
+
},
|
|
216
|
+
default: {
|
|
217
|
+
top: '0',
|
|
218
|
+
bottom: '0'
|
|
219
|
+
}
|
|
220
|
+
};
|
|
123
221
|
|
|
124
222
|
// This table contains the "margins" of different nodes
|
|
125
223
|
// Note this is not the actually margin of the DOM elements,
|
|
@@ -221,4 +319,5 @@ export const DEFAULT_COLUMN_DISTRIBUTIONS = {
|
|
|
221
319
|
3: 33.33,
|
|
222
320
|
4: 25,
|
|
223
321
|
5: 20
|
|
224
|
-
};
|
|
322
|
+
};
|
|
323
|
+
export const BLOCK_MENU_WIDTH = 220;
|
|
@@ -13,6 +13,7 @@ import { dragToMoveDown, dragToMoveLeft, dragToMoveRight, dragToMoveUp, getAriaK
|
|
|
13
13
|
import { blockControlsMessages } from '@atlaskit/editor-common/messages';
|
|
14
14
|
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
15
15
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
16
|
+
import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
|
|
16
17
|
import DragHandlerIcon from '@atlaskit/icon/glyph/drag-handler';
|
|
17
18
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
18
19
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
@@ -23,9 +24,8 @@ import Tooltip from '@atlaskit/tooltip';
|
|
|
23
24
|
import { key } from '../pm-plugins/main';
|
|
24
25
|
import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
|
|
25
26
|
import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, topPositionAdjustment } from './consts';
|
|
27
|
+
import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
|
|
28
|
+
import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, topPositionAdjustment } from './consts';
|
|
29
29
|
import { dragPreview } from './drag-preview';
|
|
30
30
|
const iconWrapperStyles = xcss({
|
|
31
31
|
display: 'flex',
|
|
@@ -96,6 +96,16 @@ const handleIconDragStart = e => {
|
|
|
96
96
|
(_e$target$closest = e.target.closest('button')) === null || _e$target$closest === void 0 ? void 0 : _e$target$closest.dispatchEvent(dragEvent);
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
|
+
const getNodeSpacingForPreview = node => {
|
|
100
|
+
if (!node) {
|
|
101
|
+
return spacingBetweenNodesForPreview['default'];
|
|
102
|
+
}
|
|
103
|
+
const nodeTypeName = node.type.name;
|
|
104
|
+
if (nodeTypeName === 'heading') {
|
|
105
|
+
return spacingBetweenNodesForPreview[`heading${node.attrs.level}`] || spacingBetweenNodesForPreview['default'];
|
|
106
|
+
}
|
|
107
|
+
return spacingBetweenNodesForPreview[nodeTypeName] || spacingBetweenNodesForPreview['default'];
|
|
108
|
+
};
|
|
99
109
|
export const DragHandle = ({
|
|
100
110
|
view,
|
|
101
111
|
api,
|
|
@@ -116,6 +126,9 @@ export const DragHandle = ({
|
|
|
116
126
|
} = useSharedPluginState(api, ['featureFlags']);
|
|
117
127
|
const selection = useSharedPluginStateSelector(api, 'selection.selection');
|
|
118
128
|
const isLayoutColumn = nodeType === 'layoutColumn';
|
|
129
|
+
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
130
|
+
exposure: true
|
|
131
|
+
});
|
|
119
132
|
useEffect(() => {
|
|
120
133
|
// blockCard/datasource width is rendered correctly after this decoraton does. We need to observe for changes.
|
|
121
134
|
if (nodeType === 'blockCard') {
|
|
@@ -159,7 +172,14 @@ export const DragHandle = ({
|
|
|
159
172
|
return tr;
|
|
160
173
|
});
|
|
161
174
|
view.focus();
|
|
162
|
-
|
|
175
|
+
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
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]);
|
|
163
183
|
|
|
164
184
|
// TODO - This needs to be investigated further. Drag preview generation is not always working
|
|
165
185
|
// as expected with a node selection. This workaround sets the selection to the node on mouseDown,
|
|
@@ -222,7 +242,92 @@ export const DragHandle = ({
|
|
|
222
242
|
onGenerateDragPreview: ({
|
|
223
243
|
nativeSetDragImage
|
|
224
244
|
}) => {
|
|
245
|
+
var _api$blockControls2;
|
|
246
|
+
if (isMultiSelect) {
|
|
247
|
+
var _api$core5;
|
|
248
|
+
api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.execute(({
|
|
249
|
+
tr
|
|
250
|
+
}) => {
|
|
251
|
+
const handlePos = getPos();
|
|
252
|
+
if (typeof handlePos !== 'number') {
|
|
253
|
+
return tr;
|
|
254
|
+
}
|
|
255
|
+
if (!tr.selection.empty && handlePos >= tr.selection.$from.start() - 1 && handlePos <= tr.selection.to) {
|
|
256
|
+
var _api$blockControls;
|
|
257
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.commands.setMultiSelectPositions()({
|
|
258
|
+
tr
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return tr;
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
const startPos = getPos();
|
|
265
|
+
const state = view.state;
|
|
266
|
+
const {
|
|
267
|
+
doc,
|
|
268
|
+
selection
|
|
269
|
+
} = 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
|
+
let sliceFrom = selection.from;
|
|
274
|
+
let sliceTo = selection.to;
|
|
275
|
+
if (multiSelectDnD) {
|
|
276
|
+
const {
|
|
277
|
+
anchor,
|
|
278
|
+
head
|
|
279
|
+
} = multiSelectDnD;
|
|
280
|
+
sliceFrom = Math.min(anchor, head);
|
|
281
|
+
sliceTo = Math.max(anchor, head);
|
|
282
|
+
}
|
|
283
|
+
const expandedSlice = doc.slice(sliceFrom, sliceTo);
|
|
284
|
+
const isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos <= sliceTo && expandedSlice.content.childCount > 1;
|
|
225
285
|
setCustomNativeDragPreview({
|
|
286
|
+
getOffset: () => {
|
|
287
|
+
if (!isDraggingMultiLine) {
|
|
288
|
+
return {
|
|
289
|
+
x: 0,
|
|
290
|
+
y: 0
|
|
291
|
+
};
|
|
292
|
+
} else {
|
|
293
|
+
// Calculate the offset of the preview container,
|
|
294
|
+
// So when drag multiple nodes, the preview align with the position of the selected nodes
|
|
295
|
+
const domAtPos = view.domAtPos.bind(view);
|
|
296
|
+
let domElementsHeightBeforeHandle = 0;
|
|
297
|
+
const nodesStartPos = [];
|
|
298
|
+
const nodesEndPos = [];
|
|
299
|
+
let activeNodeMarginTop = 0;
|
|
300
|
+
for (let i = 0; i < expandedSlice.content.childCount; i++) {
|
|
301
|
+
if (i === 0) {
|
|
302
|
+
var _expandedSlice$conten;
|
|
303
|
+
nodesStartPos[i] = sliceFrom;
|
|
304
|
+
nodesEndPos[i] = sliceFrom + (((_expandedSlice$conten = expandedSlice.content.maybeChild(i)) === null || _expandedSlice$conten === void 0 ? void 0 : _expandedSlice$conten.nodeSize) || 0);
|
|
305
|
+
} else {
|
|
306
|
+
var _expandedSlice$conten2;
|
|
307
|
+
nodesStartPos[i] = nodesEndPos[i - 1];
|
|
308
|
+
nodesEndPos[i] = nodesStartPos[i] + (((_expandedSlice$conten2 = expandedSlice.content.maybeChild(i)) === null || _expandedSlice$conten2 === void 0 ? void 0 : _expandedSlice$conten2.nodeSize) || 0);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// when the node is before the handle, calculate the height of the node
|
|
312
|
+
if (nodesEndPos[i] <= startPos) {
|
|
313
|
+
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
314
|
+
const currentNodeElement = findDomRefAtPos(nodesStartPos[i], domAtPos);
|
|
315
|
+
const maybeCurrentNode = expandedSlice.content.maybeChild(i);
|
|
316
|
+
const currentNodeSpacing = maybeCurrentNode ? nodeMargins[maybeCurrentNode.type.name].top + nodeMargins[maybeCurrentNode.type.name].bottom : 0;
|
|
317
|
+
domElementsHeightBeforeHandle = domElementsHeightBeforeHandle + currentNodeElement.offsetHeight + currentNodeSpacing;
|
|
318
|
+
} else {
|
|
319
|
+
// when the node is after the handle, calculate the top margin of the active node
|
|
320
|
+
const maybeNextNode = expandedSlice.content.maybeChild(i);
|
|
321
|
+
activeNodeMarginTop = maybeNextNode ? nodeMargins[maybeNextNode.type.name].top : 0;
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
x: 0,
|
|
327
|
+
y: domElementsHeightBeforeHandle + activeNodeMarginTop
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
},
|
|
226
331
|
render: ({
|
|
227
332
|
container
|
|
228
333
|
}) => {
|
|
@@ -230,49 +335,54 @@ export const DragHandle = ({
|
|
|
230
335
|
if (!dom) {
|
|
231
336
|
return;
|
|
232
337
|
}
|
|
233
|
-
|
|
338
|
+
if (!isDraggingMultiLine) {
|
|
339
|
+
return dragPreview(container, {
|
|
340
|
+
dom,
|
|
341
|
+
nodeType
|
|
342
|
+
});
|
|
343
|
+
} else {
|
|
344
|
+
const domAtPos = view.domAtPos.bind(view);
|
|
345
|
+
const previewContent = [];
|
|
346
|
+
expandedSlice.content.descendants((node, pos, parent, index) => {
|
|
347
|
+
// Get the dom element of the node
|
|
348
|
+
//eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
349
|
+
const nodeDomElement = findDomRefAtPos(sliceFrom + pos, domAtPos);
|
|
350
|
+
const currentNodeSpacing = getNodeSpacingForPreview(node);
|
|
351
|
+
previewContent.push({
|
|
352
|
+
dom: nodeDomElement,
|
|
353
|
+
nodeType: node.type.name,
|
|
354
|
+
nodeSpacing: currentNodeSpacing
|
|
355
|
+
});
|
|
356
|
+
return false; // Only iterate through the first level of nodes
|
|
357
|
+
});
|
|
358
|
+
return dragPreview(container, previewContent);
|
|
359
|
+
}
|
|
234
360
|
},
|
|
235
361
|
nativeSetDragImage
|
|
236
362
|
});
|
|
237
363
|
},
|
|
238
364
|
onDragStart() {
|
|
239
|
-
var _api$
|
|
365
|
+
var _api$core6;
|
|
240
366
|
if (start === undefined) {
|
|
241
367
|
return;
|
|
242
368
|
}
|
|
243
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
369
|
+
api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions.execute(({
|
|
244
370
|
tr
|
|
245
371
|
}) => {
|
|
246
|
-
var _api$
|
|
247
|
-
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
248
|
-
exposure: true
|
|
249
|
-
});
|
|
372
|
+
var _tr$getMeta, _api$blockControls3, _api$analytics3;
|
|
250
373
|
let nodeTypes, hasSelectedMultipleNodes;
|
|
251
374
|
const resolvedMovingNode = tr.doc.resolve(start);
|
|
252
375
|
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.commands.setMultiSelectPositions()({
|
|
262
|
-
tr
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
const multiSelectDnD = (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
|
|
266
|
-
if (multiSelectDnD) {
|
|
267
|
-
const attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
|
|
268
|
-
nodeTypes = attributes.nodeTypes;
|
|
269
|
-
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
270
|
-
} else {
|
|
271
|
-
nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
|
|
272
|
-
hasSelectedMultipleNodes = false;
|
|
273
|
-
}
|
|
376
|
+
const multiSelectDnD = (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
|
|
377
|
+
if (multiSelectDnD) {
|
|
378
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
|
|
379
|
+
nodeTypes = attributes.nodeTypes;
|
|
380
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
381
|
+
} else {
|
|
382
|
+
nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
|
|
383
|
+
hasSelectedMultipleNodes = false;
|
|
274
384
|
}
|
|
275
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
385
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.setNodeDragged(getPos, anchorName, nodeType)({
|
|
276
386
|
tr
|
|
277
387
|
});
|
|
278
388
|
tr.setMeta('scrollIntoView', false);
|
|
@@ -295,7 +405,7 @@ export const DragHandle = ({
|
|
|
295
405
|
view.focus();
|
|
296
406
|
}
|
|
297
407
|
});
|
|
298
|
-
}, [anchorName, api, getPos, nodeType, start, view]);
|
|
408
|
+
}, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
|
|
299
409
|
const macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
|
|
300
410
|
const calculatePosition = useCallback(() => {
|
|
301
411
|
let parentNodeType;
|
|
@@ -377,14 +487,11 @@ export const DragHandle = ({
|
|
|
377
487
|
}
|
|
378
488
|
}, [buttonRef, handleOptions === null || handleOptions === void 0 ? void 0 : handleOptions.isFocused, view]);
|
|
379
489
|
useEffect(() => {
|
|
380
|
-
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
381
|
-
exposure: true
|
|
382
|
-
});
|
|
383
490
|
if (!isMultiSelect || typeof start !== 'number' || !selection) {
|
|
384
491
|
return;
|
|
385
492
|
}
|
|
386
|
-
setDragHandleSelected(
|
|
387
|
-
}, [start, selection, view.state]);
|
|
493
|
+
setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
|
|
494
|
+
}, [start, selection, view.state, isMultiSelect]);
|
|
388
495
|
let helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
|
|
389
496
|
description: formatMessage(blockControlsMessages.dragToMove)
|
|
390
497
|
}, {
|
|
@@ -410,7 +517,12 @@ export const DragHandle = ({
|
|
|
410
517
|
}];
|
|
411
518
|
let isParentNodeOfTypeLayout;
|
|
412
519
|
if (!isTopLevelNode && (fg('platform_editor_advanced_layouts_accessibility') || handleOptions !== null && handleOptions !== void 0 && handleOptions.isFocused) && editorExperiment('nested-dnd', true)) {
|
|
413
|
-
|
|
520
|
+
const pos = getPos();
|
|
521
|
+
if (typeof pos === 'number') {
|
|
522
|
+
var _$pos$parent;
|
|
523
|
+
const $pos = view.state.doc.resolve(pos);
|
|
524
|
+
isParentNodeOfTypeLayout = ($pos === null || $pos === void 0 ? void 0 : (_$pos$parent = $pos.parent) === null || _$pos$parent === void 0 ? void 0 : _$pos$parent.type.name) === 'layoutColumn';
|
|
525
|
+
}
|
|
414
526
|
if (isParentNodeOfTypeLayout) {
|
|
415
527
|
helpDescriptors = [...helpDescriptors, {
|
|
416
528
|
description: formatMessage(blockControlsMessages.moveLeft),
|
|
@@ -15,14 +15,8 @@ const previewStyleOld = {
|
|
|
15
15
|
borderWidth: "var(--ds-border-width-outline, 2px)",
|
|
16
16
|
backgroundColor: "var(--ds-blanket-selected, #388BFF14)"
|
|
17
17
|
};
|
|
18
|
-
|
|
18
|
+
const getPreviewContainerDimensionsForSingle = (dom, nodeType) => {
|
|
19
19
|
let nodeContainer = dom;
|
|
20
|
-
container.style.pointerEvents = 'none';
|
|
21
|
-
const parent = document.createElement('div');
|
|
22
|
-
// ProseMirror class is required to make sure the cloned dom is styled correctly
|
|
23
|
-
parent.classList.add('ProseMirror', 'block-ctrl-drag-preview');
|
|
24
|
-
const embedCard = dom.querySelector('.embedCardView-content-wrap');
|
|
25
|
-
let shouldBeGenericPreview = nodeType === 'embedCard' || nodeType === 'extension' || !!embedCard;
|
|
26
20
|
if (fg('platform_editor_elements_drag_and_drop_ed_23189')) {
|
|
27
21
|
const iframeContainer = dom.querySelector('iframe');
|
|
28
22
|
if (nodeType === 'embedCard') {
|
|
@@ -30,41 +24,96 @@ export const dragPreview = (container, dom, nodeType) => {
|
|
|
30
24
|
} else if (nodeType === 'extension' && iframeContainer) {
|
|
31
25
|
nodeContainer = iframeContainer;
|
|
32
26
|
}
|
|
33
|
-
shouldBeGenericPreview = nodeType === 'embedCard' || !!embedCard || nodeType === 'extension' && !!iframeContainer;
|
|
34
27
|
}
|
|
35
28
|
const nodeContainerRect = nodeContainer.getBoundingClientRect();
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
return {
|
|
30
|
+
width: nodeContainerRect.width,
|
|
31
|
+
height: nodeContainerRect.height
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const getPreviewContainerDimensions = dragPreviewContent => {
|
|
35
|
+
let maxWidth = 0;
|
|
36
|
+
let heightSum = 0;
|
|
37
|
+
for (let index = 0; index < dragPreviewContent.length; index++) {
|
|
38
|
+
const element = dragPreviewContent[index];
|
|
39
|
+
const {
|
|
40
|
+
width,
|
|
41
|
+
height
|
|
42
|
+
} = getPreviewContainerDimensionsForSingle(element.dom, element.nodeType);
|
|
43
|
+
if (width > maxWidth) {
|
|
44
|
+
maxWidth = width;
|
|
45
|
+
}
|
|
46
|
+
heightSum += height;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
width: maxWidth,
|
|
50
|
+
height: heightSum
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const createGenericPreview = () => {
|
|
54
|
+
const generalPreview = document.createElement('div');
|
|
55
|
+
// ProseMirror class is required to make sure the cloned dom is styled correctly
|
|
56
|
+
generalPreview.classList.add('ProseMirror', 'block-ctrl-drag-preview');
|
|
38
57
|
const previewStyle = fg('platform_editor_elements_drag_and_drop_ed_23189') ? previewStyleNew : previewStyleOld;
|
|
58
|
+
generalPreview.style.border = `${previewStyle.borderWidth} ${previewStyle.borderStyle} ${previewStyle.borderColor}`;
|
|
59
|
+
generalPreview.style.borderRadius = previewStyle.borderRadius;
|
|
60
|
+
generalPreview.style.backgroundColor = previewStyle.backgroundColor;
|
|
61
|
+
generalPreview.style.height = '100%';
|
|
62
|
+
generalPreview.setAttribute('data-testid', 'block-ctrl-generic-drag-preview');
|
|
63
|
+
return generalPreview;
|
|
64
|
+
};
|
|
65
|
+
const createContentPreviewElement = (dom, nodeType, nodeSpacing) => {
|
|
66
|
+
const contentPreviewOneElement = document.createElement('div');
|
|
67
|
+
contentPreviewOneElement.classList.add('ProseMirror', 'block-ctrl-drag-preview');
|
|
68
|
+
const resizer = dom.querySelector('.resizer-item');
|
|
69
|
+
const clonedDom = resizer && ['mediaSingle', 'table'].includes(nodeType) ?
|
|
70
|
+
// Ignored via go/ees005
|
|
71
|
+
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
72
|
+
resizer.cloneNode(true) :
|
|
73
|
+
// Ignored via go/ees005
|
|
74
|
+
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
75
|
+
dom.cloneNode(true);
|
|
76
|
+
clonedDom.style.marginLeft = '0';
|
|
77
|
+
clonedDom.style.marginTop = nodeSpacing ? `${nodeSpacing.top}` : '0';
|
|
78
|
+
clonedDom.style.marginRight = '0';
|
|
79
|
+
clonedDom.style.marginBottom = nodeSpacing ? `${nodeSpacing.bottom}` : '0';
|
|
80
|
+
clonedDom.style.boxShadow = 'none';
|
|
81
|
+
clonedDom.style.opacity = browser.windows ? '1' : fg('platform_editor_elements_drag_and_drop_ed_23189') ? '0.31' : '0.4';
|
|
82
|
+
contentPreviewOneElement.appendChild(clonedDom);
|
|
83
|
+
return contentPreviewOneElement;
|
|
84
|
+
};
|
|
85
|
+
const isGenericPreview = (dom, nodeType) => {
|
|
86
|
+
const embedCard = dom.querySelector('.embedCardView-content-wrap');
|
|
87
|
+
return fg('platform_editor_elements_drag_and_drop_ed_23189') ? nodeType === 'embedCard' || !!embedCard || nodeType === 'extension' && !!dom.querySelector('iframe') : nodeType === 'embedCard' || !!embedCard || nodeType === 'extension';
|
|
88
|
+
};
|
|
89
|
+
const createPreviewForElement = (dom, nodeType, nodeSpacing) => {
|
|
90
|
+
const shouldBeGenericPreview = isGenericPreview(dom, nodeType);
|
|
39
91
|
if (shouldBeGenericPreview) {
|
|
40
|
-
|
|
41
|
-
parent.style.borderRadius = previewStyle.borderRadius;
|
|
42
|
-
parent.style.backgroundColor = previewStyle.backgroundColor;
|
|
43
|
-
parent.style.height = '100%';
|
|
44
|
-
parent.setAttribute('data-testid', 'block-ctrl-generic-drag-preview');
|
|
92
|
+
return createGenericPreview();
|
|
45
93
|
} else {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
94
|
+
return createContentPreviewElement(dom, nodeType, nodeSpacing);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
export const dragPreview = (container, dragPreviewContent) => {
|
|
98
|
+
container.style.pointerEvents = 'none';
|
|
99
|
+
if (!Array.isArray(dragPreviewContent) && typeof dragPreviewContent === 'object') {
|
|
100
|
+
dragPreviewContent = [dragPreviewContent];
|
|
101
|
+
}
|
|
102
|
+
const {
|
|
103
|
+
width: maxWidth,
|
|
104
|
+
height: maxHeight
|
|
105
|
+
} = getPreviewContainerDimensions(dragPreviewContent);
|
|
106
|
+
container.style.width = `${maxWidth}px`;
|
|
107
|
+
container.style.height = `${maxHeight}px`;
|
|
108
|
+
const previewWrapperFragment = document.createDocumentFragment();
|
|
109
|
+
for (let index = 0; index < dragPreviewContent.length; index++) {
|
|
110
|
+
const element = dragPreviewContent[index];
|
|
111
|
+
const contentPreviewOneElement = createPreviewForElement(element.dom, element.nodeType, element.nodeSpacing);
|
|
112
|
+
previewWrapperFragment.appendChild(contentPreviewOneElement);
|
|
63
113
|
}
|
|
64
|
-
container.appendChild(
|
|
114
|
+
container.appendChild(previewWrapperFragment);
|
|
65
115
|
const scrollParent = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
66
116
|
const scrollParentClassNames = scrollParent === null || scrollParent === void 0 ? void 0 : scrollParent.className;
|
|
67
|
-
|
|
68
117
|
// Add the scroll parent class to the container to ensure the cloned element is styled correctly
|
|
69
118
|
container.className = scrollParentClassNames || '';
|
|
70
119
|
container.classList.remove('fabric-editor-popup-scroll-parent');
|