@atlaskit/editor-plugin-block-controls 2.10.0 → 2.11.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 +19 -0
- package/dist/cjs/pm-plugins/decorations-anchor.js +97 -0
- package/dist/cjs/pm-plugins/decorations-common.js +49 -0
- package/dist/cjs/pm-plugins/decorations-drag-handle.js +88 -0
- package/dist/cjs/pm-plugins/{decorations.js → decorations-drop-target.js} +11 -209
- package/dist/cjs/pm-plugins/main.js +21 -19
- package/dist/cjs/ui/drop-target-v2.js +3 -3
- package/dist/cjs/ui/global-styles.js +101 -86
- package/dist/cjs/ui/inline-drop-target.js +3 -3
- package/dist/es2019/pm-plugins/decorations-anchor.js +89 -0
- package/dist/es2019/pm-plugins/decorations-common.js +31 -0
- package/dist/es2019/pm-plugins/decorations-drag-handle.js +79 -0
- package/dist/es2019/pm-plugins/{decorations.js → decorations-drop-target.js} +6 -193
- package/dist/es2019/pm-plugins/main.js +3 -1
- package/dist/es2019/ui/drop-target-v2.js +1 -1
- package/dist/es2019/ui/global-styles.js +17 -6
- package/dist/es2019/ui/inline-drop-target.js +1 -1
- package/dist/esm/pm-plugins/decorations-anchor.js +90 -0
- package/dist/esm/pm-plugins/decorations-common.js +42 -0
- package/dist/esm/pm-plugins/decorations-drag-handle.js +81 -0
- package/dist/esm/pm-plugins/{decorations.js → decorations-drop-target.js} +6 -204
- package/dist/esm/pm-plugins/main.js +3 -1
- package/dist/esm/ui/drop-target-v2.js +1 -1
- package/dist/esm/ui/global-styles.js +101 -86
- package/dist/esm/ui/inline-drop-target.js +1 -1
- package/dist/types/pm-plugins/decorations-anchor.d.ts +13 -0
- package/dist/types/pm-plugins/decorations-common.d.ts +7 -0
- package/dist/types/pm-plugins/decorations-drag-handle.d.ts +7 -0
- package/dist/types/pm-plugins/decorations-drop-target.d.ts +17 -0
- package/dist/types-ts4.5/pm-plugins/decorations-anchor.d.ts +13 -0
- package/dist/types-ts4.5/pm-plugins/decorations-common.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/decorations-drag-handle.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/decorations-drop-target.d.ts +17 -0
- package/package.json +4 -4
- package/dist/types/pm-plugins/decorations.d.ts +0 -35
- package/dist/types-ts4.5/pm-plugins/decorations.d.ts +0 -35
|
@@ -1,29 +1,23 @@
|
|
|
1
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
1
|
import { createElement } from 'react';
|
|
3
|
-
import { bind } from 'bind-event-listener';
|
|
4
2
|
import ReactDOM from 'react-dom';
|
|
5
|
-
import uuid from 'uuid';
|
|
6
3
|
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
|
|
7
4
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
8
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
6
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
10
7
|
import { nodeMargins } from '../ui/consts';
|
|
11
|
-
import { DragHandle } from '../ui/drag-handle';
|
|
12
8
|
import { DropTarget } from '../ui/drop-target';
|
|
13
9
|
import { DropTargetV2, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET } from '../ui/drop-target-v2';
|
|
14
10
|
import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
|
|
15
11
|
import { canMoveNodeToIndex } from '../utils/validation';
|
|
12
|
+
import { getNestedDepth, TYPE_DROP_TARGET_DEC, unmountDecorations } from './decorations-common';
|
|
16
13
|
const IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn', 'listItem', 'caption'];
|
|
17
|
-
const IGNORE_NODE_DESCENDANTS = ['listItem', 'taskList', 'decisionList', 'mediaSingle'];
|
|
18
14
|
const PARENT_WITH_END_DROP_TARGET = ['tableCell', 'tableHeader', 'panel', 'layoutColumn', 'expand', 'nestedExpand', 'bodiedExtension'];
|
|
19
15
|
const DISABLE_CHILD_DROP_TARGET = ['orderedList', 'bulletList'];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const handleId = ObjHash.getForNode(node);
|
|
26
|
-
return `--node-anchor-${node.type.name}-${handleId}`;
|
|
16
|
+
const shouldDescend = node => {
|
|
17
|
+
if (fg('platform_editor_drag_and_drop_target_v2')) {
|
|
18
|
+
return !['mediaSingle', 'paragraph', 'heading'].includes(node.type.name);
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
27
21
|
};
|
|
28
22
|
const getNodeMargins = node => {
|
|
29
23
|
if (!node) {
|
|
@@ -68,12 +62,6 @@ const getGapAndOffset = (prevNode, nextNode, parentNode) => {
|
|
|
68
62
|
offset
|
|
69
63
|
};
|
|
70
64
|
};
|
|
71
|
-
const shouldDescend = node => {
|
|
72
|
-
if (fg('platform_editor_drag_and_drop_target_v2')) {
|
|
73
|
-
return !['mediaSingle', 'paragraph', 'heading'].includes(node.type.name);
|
|
74
|
-
}
|
|
75
|
-
return true;
|
|
76
|
-
};
|
|
77
65
|
|
|
78
66
|
/**
|
|
79
67
|
* Find drop target decorations in the pos range between from and to
|
|
@@ -85,37 +73,6 @@ const shouldDescend = node => {
|
|
|
85
73
|
export const findDropTargetDecs = (decorations, from, to) => {
|
|
86
74
|
return decorations.find(from, to, spec => spec.type === TYPE_DROP_TARGET_DEC);
|
|
87
75
|
};
|
|
88
|
-
export const findHandleDec = (decorations, from, to) => {
|
|
89
|
-
return decorations.find(from, to, spec => spec.type === TYPE_HANDLE_DEC);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Find node decorations in the pos range between from and to (non-inclusive)
|
|
94
|
-
* @param decorations
|
|
95
|
-
* @param from
|
|
96
|
-
* @param to
|
|
97
|
-
* @returns
|
|
98
|
-
*/
|
|
99
|
-
export const findNodeDecs = (decorations, from, to) => {
|
|
100
|
-
let newfrom = from;
|
|
101
|
-
let newTo = to;
|
|
102
|
-
|
|
103
|
-
// make it non-inclusive
|
|
104
|
-
if (newfrom !== undefined) {
|
|
105
|
-
newfrom++;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// make it non-inclusive
|
|
109
|
-
if (newTo !== undefined) {
|
|
110
|
-
newTo--;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// return empty array if range reversed
|
|
114
|
-
if (newfrom !== undefined && newTo !== undefined && newfrom > newTo) {
|
|
115
|
-
return new Array();
|
|
116
|
-
}
|
|
117
|
-
return decorations.find(newfrom, newTo, spec => spec.type === TYPE_NODE_DEC);
|
|
118
|
-
};
|
|
119
76
|
export const createDropTargetDecoration = (pos, props, side, anchorRectCache) => {
|
|
120
77
|
return Decoration.widget(pos, (_, getPos) => {
|
|
121
78
|
const element = document.createElement('div');
|
|
@@ -244,148 +201,4 @@ export const dropTargetDecorations = (newState, api, formatMessage, activeNode,
|
|
|
244
201
|
}, undefined, anchorRectCache));
|
|
245
202
|
}
|
|
246
203
|
return decs;
|
|
247
|
-
};
|
|
248
|
-
export const emptyParagraphNodeDecorations = () => {
|
|
249
|
-
const anchorName = `--node-anchor-paragraph-0`;
|
|
250
|
-
const style = `anchor-name: ${anchorName}; margin-top: 0px;`;
|
|
251
|
-
return Decoration.node(0, 2, {
|
|
252
|
-
style,
|
|
253
|
-
['data-drag-handler-anchor-name']: anchorName
|
|
254
|
-
}, {
|
|
255
|
-
type: TYPE_NODE_DEC
|
|
256
|
-
});
|
|
257
|
-
};
|
|
258
|
-
class ObjHash {
|
|
259
|
-
static getForNode(node) {
|
|
260
|
-
if (this.caching.has(node)) {
|
|
261
|
-
return this.caching.get(node);
|
|
262
|
-
}
|
|
263
|
-
const uniqueId = uuid();
|
|
264
|
-
this.caching.set(node, uniqueId);
|
|
265
|
-
return uniqueId;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
_defineProperty(ObjHash, "caching", new WeakMap());
|
|
269
|
-
const shouldIgnoreNode = node => {
|
|
270
|
-
// TODO use isWrappedMedia when clean up the featue flag
|
|
271
|
-
if ('mediaSingle' === node.type.name && fg('platform_editor_element_dnd_nested_fix_patch_1')) {
|
|
272
|
-
if (['wrap-right', 'wrap-left'].includes(node.attrs.layout)) {
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
return IGNORE_NODES.includes(node.type.name);
|
|
277
|
-
};
|
|
278
|
-
export const shouldDescendIntoNode = node => {
|
|
279
|
-
// Optimisation to avoid drawing node decorations for empty table cells
|
|
280
|
-
if (['tableCell', 'tableHeader'].includes(node.type.name) && !editorExperiment('table-nested-dnd', true) && fg('platform_editor_element_dnd_nested_fix_patch_3')) {
|
|
281
|
-
var _node$firstChild;
|
|
282
|
-
if (node.childCount === 1 && ((_node$firstChild = node.firstChild) === null || _node$firstChild === void 0 ? void 0 : _node$firstChild.type.name) === 'paragraph') {
|
|
283
|
-
return false;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return !IGNORE_NODE_DESCENDANTS.includes(node.type.name);
|
|
287
|
-
};
|
|
288
|
-
export const nodeDecorations = (newState, from, to) => {
|
|
289
|
-
const decs = [];
|
|
290
|
-
const docFrom = from === undefined || from < 0 ? 0 : from;
|
|
291
|
-
const docTo = to === undefined || to > newState.doc.nodeSize - 2 ? newState.doc.nodeSize - 2 : to;
|
|
292
|
-
newState.doc.nodesBetween(docFrom, docTo, (node, pos, _parent, index) => {
|
|
293
|
-
let depth = 0;
|
|
294
|
-
let anchorName;
|
|
295
|
-
const shouldDescend = shouldDescendIntoNode(node);
|
|
296
|
-
const handleId = ObjHash.getForNode(node);
|
|
297
|
-
anchorName = `--node-anchor-${node.type.name}-${handleId}`;
|
|
298
|
-
if (editorExperiment('nested-dnd', true)) {
|
|
299
|
-
var _anchorName;
|
|
300
|
-
// Doesn't descend into a node
|
|
301
|
-
if (node.isInline) {
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
if (shouldIgnoreNode(node)) {
|
|
305
|
-
return shouldDescend; //skip over, don't consider it a valid depth
|
|
306
|
-
}
|
|
307
|
-
depth = newState.doc.resolve(pos).depth;
|
|
308
|
-
anchorName = (_anchorName = anchorName) !== null && _anchorName !== void 0 ? _anchorName : `--node-anchor-${node.type.name}-${pos}`;
|
|
309
|
-
} else {
|
|
310
|
-
var _anchorName2;
|
|
311
|
-
anchorName = (_anchorName2 = anchorName) !== null && _anchorName2 !== void 0 ? _anchorName2 : `--node-anchor-${node.type.name}-${index}`;
|
|
312
|
-
}
|
|
313
|
-
decs.push(Decoration.node(pos, pos + node.nodeSize, {
|
|
314
|
-
style: `anchor-name: ${anchorName}; ${pos === 0 ? 'margin-top: 0px;' : ''}; position: relative; z-index: 1;`,
|
|
315
|
-
['data-drag-handler-anchor-name']: anchorName,
|
|
316
|
-
['data-drag-handler-node-type']: node.type.name,
|
|
317
|
-
['data-drag-handler-anchor-depth']: `${depth}`
|
|
318
|
-
}, {
|
|
319
|
-
type: TYPE_NODE_DEC,
|
|
320
|
-
anchorName,
|
|
321
|
-
nodeType: node.type.name
|
|
322
|
-
}));
|
|
323
|
-
return shouldDescend && depth < getNestedDepth();
|
|
324
|
-
});
|
|
325
|
-
return decs;
|
|
326
|
-
};
|
|
327
|
-
export const dragHandleDecoration = (api, formatMessage, pos, anchorName, nodeType, handleOptions) => {
|
|
328
|
-
unmountDecorations('data-blocks-drag-handle-container');
|
|
329
|
-
let unbind;
|
|
330
|
-
return Decoration.widget(pos, (view, getPos) => {
|
|
331
|
-
const element = document.createElement('span');
|
|
332
|
-
// Need to set it to inline to avoid text being split when merging two paragraphs
|
|
333
|
-
// platform_editor_element_dnd_nested_fix_patch_2 -> inline decoration causes focus issues when refocusing Editor into first line
|
|
334
|
-
element.style.display = fg('platform_editor_element_dnd_nested_fix_patch_2') ? 'block' : 'inline';
|
|
335
|
-
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
336
|
-
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
337
|
-
let isTopLevelNode = true;
|
|
338
|
-
if (editorExperiment('nested-dnd', true)) {
|
|
339
|
-
const newPos = fg('platform_editor_element_dnd_nested_fix_patch_3') ? getPos() : pos;
|
|
340
|
-
if (typeof newPos === 'number') {
|
|
341
|
-
const $pos = view.state.doc.resolve(newPos);
|
|
342
|
-
isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
|
|
343
|
-
}
|
|
344
|
-
/*
|
|
345
|
-
* We disable mouseover event to fix flickering issue on hover
|
|
346
|
-
* However, the tooltip for nested drag handle is no long working.
|
|
347
|
-
*/
|
|
348
|
-
if (newPos === undefined || !isTopLevelNode) {
|
|
349
|
-
// This will also hide the tooltip.
|
|
350
|
-
unbind = bind(element, {
|
|
351
|
-
type: 'mouseover',
|
|
352
|
-
listener: e => {
|
|
353
|
-
e.stopPropagation();
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// There are times when global clear: "both" styles are applied to this decoration causing jumpiness
|
|
360
|
-
// due to margins applied to other nodes eg. Headings
|
|
361
|
-
element.style.clear = 'unset';
|
|
362
|
-
ReactDOM.render( /*#__PURE__*/createElement(DragHandle, {
|
|
363
|
-
view,
|
|
364
|
-
api,
|
|
365
|
-
formatMessage,
|
|
366
|
-
getPos,
|
|
367
|
-
anchorName,
|
|
368
|
-
nodeType,
|
|
369
|
-
handleOptions,
|
|
370
|
-
isTopLevelNode
|
|
371
|
-
}), element);
|
|
372
|
-
return element;
|
|
373
|
-
}, {
|
|
374
|
-
side: -1,
|
|
375
|
-
type: TYPE_HANDLE_DEC,
|
|
376
|
-
testid: `${TYPE_HANDLE_DEC}-${uuid()}`,
|
|
377
|
-
destroy: () => {
|
|
378
|
-
if (editorExperiment('nested-dnd', true)) {
|
|
379
|
-
unbind && unbind();
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
};
|
|
384
|
-
const unmountDecorations = selector => {
|
|
385
|
-
// Removing decorations manually instead of using native destroy function in prosemirror API
|
|
386
|
-
// as it was more responsive and causes less re-rendering
|
|
387
|
-
const decorationsToRemove = document.querySelectorAll(`[${selector}="true"]`);
|
|
388
|
-
decorationsToRemove.forEach(el => {
|
|
389
|
-
ReactDOM.unmountComponentAtNode(el);
|
|
390
|
-
});
|
|
391
204
|
};
|
|
@@ -14,7 +14,9 @@ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
|
14
14
|
import { AnchorRectCache, isAnchorSupported } from '../utils/anchor-utils';
|
|
15
15
|
import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
|
|
16
16
|
import { getTrMetadata } from '../utils/transactions';
|
|
17
|
-
import {
|
|
17
|
+
import { findNodeDecs, nodeDecorations } from './decorations-anchor';
|
|
18
|
+
import { dragHandleDecoration, emptyParagraphNodeDecorations, findHandleDec } from './decorations-drag-handle';
|
|
19
|
+
import { dropTargetDecorations, findDropTargetDecs } from './decorations-drop-target';
|
|
18
20
|
import { handleMouseOver } from './handle-mouse-over';
|
|
19
21
|
import { boundKeydownHandler } from './keymap';
|
|
20
22
|
export const key = new PluginKey('blockControls');
|
|
@@ -12,7 +12,7 @@ import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indi
|
|
|
12
12
|
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
13
13
|
import { layers } from '@atlaskit/theme/constants';
|
|
14
14
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
15
|
-
import { getNodeAnchor } from '../pm-plugins/decorations';
|
|
15
|
+
import { getNodeAnchor } from '../pm-plugins/decorations-common';
|
|
16
16
|
import { isAnchorSupported } from '../utils/anchor-utils';
|
|
17
17
|
import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
|
|
18
18
|
import { shouldAllowInlineDropTarget } from '../utils/inline-drop-target';
|
|
@@ -8,7 +8,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
|
|
|
8
8
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
9
9
|
import { DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
|
|
10
10
|
import { emptyBlockExperimentGlobalStyles } from './empty-block-experiment/global-styles';
|
|
11
|
-
const extendedHoverZone = css({
|
|
11
|
+
const extendedHoverZone = () => css({
|
|
12
12
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
13
13
|
'.block-ctrl-drag-preview [data-drag-handler-anchor-name]::after': {
|
|
14
14
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
|
|
@@ -26,7 +26,8 @@ const extendedHoverZone = css({
|
|
|
26
26
|
height: '100%',
|
|
27
27
|
background: 'transparent',
|
|
28
28
|
cursor: 'default',
|
|
29
|
-
|
|
29
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
|
|
30
|
+
zIndex: fg('platform_editor_element_dnd_nested_fix_patch_3') ? 1 : -1
|
|
30
31
|
}
|
|
31
32
|
},
|
|
32
33
|
// TODO - ED-23995 this style override needs to be moved to the Rule styles after FF cleanup - packages/editor/editor-common/src/styles/shared/rule.ts
|
|
@@ -39,7 +40,7 @@ const extendedHoverZone = css({
|
|
|
39
40
|
display: 'none'
|
|
40
41
|
}
|
|
41
42
|
});
|
|
42
|
-
const extendedHoverZoneNested = css({
|
|
43
|
+
const extendedHoverZoneNested = () => css({
|
|
43
44
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
44
45
|
'.block-ctrl-drag-preview [data-drag-handler-anchor-name]::after': {
|
|
45
46
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
|
|
@@ -69,7 +70,8 @@ const extendedHoverZoneNested = css({
|
|
|
69
70
|
width: '100%',
|
|
70
71
|
height: '100%',
|
|
71
72
|
cursor: 'default',
|
|
72
|
-
|
|
73
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
|
|
74
|
+
zIndex: fg('platform_editor_element_dnd_nested_fix_patch_3') ? 1 : -1
|
|
73
75
|
},
|
|
74
76
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
75
77
|
'&& :is(.pm-table-cell-content-wrap, .pm-table-header-content-wrap) > [data-drag-handler-anchor-name]::after': {
|
|
@@ -166,10 +168,19 @@ const withFormatInLayoutStyleFix = css({
|
|
|
166
168
|
const getTextNodeStyle = () => {
|
|
167
169
|
return fg('platform_editor_element_controls_chrome_input_fix') ? withInlineNodeStyleWithChromeFix : withInlineNodeStyle;
|
|
168
170
|
};
|
|
171
|
+
const withRelativePosStyle = css({
|
|
172
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
173
|
+
'.ProseMirror': {
|
|
174
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
175
|
+
'&& [data-drag-handler-anchor-name]': {
|
|
176
|
+
position: 'relative'
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
169
180
|
export const GlobalStylesWrapper = () => {
|
|
170
181
|
return jsx(Global, {
|
|
171
|
-
styles: [globalStyles, editorExperiment('nested-dnd', true) ? extendedHoverZoneNested : extendedHoverZone, getTextNodeStyle(), withDeleteLinesStyleFix, withMediaSingleStyleFix, editorExperiment('platform_editor_empty_line_prompt', true, {
|
|
182
|
+
styles: [globalStyles, editorExperiment('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), getTextNodeStyle(), withDeleteLinesStyleFix, withMediaSingleStyleFix, editorExperiment('platform_editor_empty_line_prompt', true, {
|
|
172
183
|
exposure: false
|
|
173
|
-
}) ? emptyBlockExperimentGlobalStyles : undefined, fg('platform_editor_element_dnd_nested_fix_patch_1') ? withDividerInPanelStyleFix : undefined, fg('platform_editor_element_dnd_nested_fix_patch_2') ? withFormatInLayoutStyleFix : undefined]
|
|
184
|
+
}) ? emptyBlockExperimentGlobalStyles : undefined, fg('platform_editor_element_dnd_nested_fix_patch_1') ? withDividerInPanelStyleFix : undefined, fg('platform_editor_element_dnd_nested_fix_patch_2') ? withFormatInLayoutStyleFix : undefined, fg('platform_editor_element_dnd_nested_fix_patch_3') ? withRelativePosStyle : undefined]
|
|
174
185
|
});
|
|
175
186
|
};
|
|
@@ -11,7 +11,7 @@ import { css, jsx } from '@emotion/react';
|
|
|
11
11
|
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
12
12
|
import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
|
|
13
13
|
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
14
|
-
import { getNodeAnchor } from '../pm-plugins/decorations';
|
|
14
|
+
import { getNodeAnchor } from '../pm-plugins/decorations-common';
|
|
15
15
|
import { isAnchorSupported } from '../utils/anchor-utils';
|
|
16
16
|
import { isBlocksDragTargetDebug } from '../utils/drag-target-debug';
|
|
17
17
|
const dropTargetCommonStyle = css({
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
5
|
+
import { getNestedDepth, getNodeAnchor, TYPE_NODE_DEC } from './decorations-common';
|
|
6
|
+
var IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn', 'listItem', 'caption'];
|
|
7
|
+
var IGNORE_NODE_DESCENDANTS = ['listItem', 'taskList', 'decisionList', 'mediaSingle'];
|
|
8
|
+
export var shouldDescendIntoNode = function shouldDescendIntoNode(node) {
|
|
9
|
+
// Optimisation to avoid drawing node decorations for empty table cells
|
|
10
|
+
if (['tableCell', 'tableHeader'].includes(node.type.name) && !editorExperiment('table-nested-dnd', true) && fg('platform_editor_element_dnd_nested_fix_patch_3')) {
|
|
11
|
+
var _node$firstChild;
|
|
12
|
+
if (node.childCount === 1 && ((_node$firstChild = node.firstChild) === null || _node$firstChild === void 0 ? void 0 : _node$firstChild.type.name) === 'paragraph') {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return !IGNORE_NODE_DESCENDANTS.includes(node.type.name);
|
|
17
|
+
};
|
|
18
|
+
var shouldIgnoreNode = function shouldIgnoreNode(node) {
|
|
19
|
+
var isEmbedCard = 'embedCard' === node.type.name && fg('platform_editor_element_dnd_nested_fix_patch_3');
|
|
20
|
+
|
|
21
|
+
// TODO use isWrappedMedia when clean up the feature flag
|
|
22
|
+
var isMediaSingle = 'mediaSingle' === node.type.name && fg('platform_editor_element_dnd_nested_fix_patch_1');
|
|
23
|
+
return (isEmbedCard || isMediaSingle) && ['wrap-right', 'wrap-left'].includes(node.attrs.layout) ? true : IGNORE_NODES.includes(node.type.name);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Find node decorations in the pos range between from and to (non-inclusive)
|
|
28
|
+
* @param decorations
|
|
29
|
+
* @param from
|
|
30
|
+
* @param to
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
export var findNodeDecs = function findNodeDecs(decorations, from, to) {
|
|
34
|
+
var newfrom = from;
|
|
35
|
+
var newTo = to;
|
|
36
|
+
|
|
37
|
+
// make it non-inclusive
|
|
38
|
+
if (newfrom !== undefined) {
|
|
39
|
+
newfrom++;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// make it non-inclusive
|
|
43
|
+
if (newTo !== undefined) {
|
|
44
|
+
newTo--;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// return empty array if range reversed
|
|
48
|
+
if (newfrom !== undefined && newTo !== undefined && newfrom > newTo) {
|
|
49
|
+
return new Array();
|
|
50
|
+
}
|
|
51
|
+
return decorations.find(newfrom, newTo, function (spec) {
|
|
52
|
+
return spec.type === TYPE_NODE_DEC;
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
export var nodeDecorations = function nodeDecorations(newState, from, to) {
|
|
56
|
+
var decs = [];
|
|
57
|
+
var docFrom = from === undefined || from < 0 ? 0 : from;
|
|
58
|
+
var docTo = to === undefined || to > newState.doc.nodeSize - 2 ? newState.doc.nodeSize - 2 : to;
|
|
59
|
+
newState.doc.nodesBetween(docFrom, docTo, function (node, pos, _parent, index) {
|
|
60
|
+
var _Decoration$node;
|
|
61
|
+
var depth = 0;
|
|
62
|
+
var anchorName;
|
|
63
|
+
var shouldDescend = shouldDescendIntoNode(node);
|
|
64
|
+
anchorName = getNodeAnchor(node);
|
|
65
|
+
if (editorExperiment('nested-dnd', true)) {
|
|
66
|
+
var _anchorName;
|
|
67
|
+
// Doesn't descend into a node
|
|
68
|
+
if (node.isInline) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (shouldIgnoreNode(node)) {
|
|
72
|
+
return shouldDescend; //skip over, don't consider it a valid depth
|
|
73
|
+
}
|
|
74
|
+
depth = newState.doc.resolve(pos).depth;
|
|
75
|
+
anchorName = (_anchorName = anchorName) !== null && _anchorName !== void 0 ? _anchorName : "--node-anchor-".concat(node.type.name, "-").concat(pos);
|
|
76
|
+
} else {
|
|
77
|
+
var _anchorName2;
|
|
78
|
+
anchorName = (_anchorName2 = anchorName) !== null && _anchorName2 !== void 0 ? _anchorName2 : "--node-anchor-".concat(node.type.name, "-").concat(index);
|
|
79
|
+
}
|
|
80
|
+
decs.push(Decoration.node(pos, pos + node.nodeSize, (_Decoration$node = {
|
|
81
|
+
style: "anchor-name: ".concat(anchorName, "; ").concat(pos === 0 ? 'margin-top: 0px;' : '', " ").concat(fg('platform_editor_element_dnd_nested_fix_patch_3') ? '' : 'position: relative; z-index: 1;')
|
|
82
|
+
}, _defineProperty(_Decoration$node, 'data-drag-handler-anchor-name', anchorName), _defineProperty(_Decoration$node, 'data-drag-handler-node-type', node.type.name), _defineProperty(_Decoration$node, 'data-drag-handler-anchor-depth', "".concat(depth)), _Decoration$node), {
|
|
83
|
+
type: TYPE_NODE_DEC,
|
|
84
|
+
anchorName: anchorName,
|
|
85
|
+
nodeType: node.type.name
|
|
86
|
+
}));
|
|
87
|
+
return shouldDescend && depth < getNestedDepth();
|
|
88
|
+
});
|
|
89
|
+
return decs;
|
|
90
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
import ReactDOM from 'react-dom';
|
|
5
|
+
import uuid from 'uuid';
|
|
6
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
7
|
+
export var TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
|
|
8
|
+
export var TYPE_HANDLE_DEC = 'drag-handle';
|
|
9
|
+
export var TYPE_NODE_DEC = 'node-decoration';
|
|
10
|
+
export var getNestedDepth = function getNestedDepth() {
|
|
11
|
+
return editorExperiment('nested-dnd', true) ? 100 : 0;
|
|
12
|
+
};
|
|
13
|
+
export var getNodeAnchor = function getNodeAnchor(node) {
|
|
14
|
+
var handleId = ObjHash.getForNode(node);
|
|
15
|
+
return "--node-anchor-".concat(node.type.name, "-").concat(handleId);
|
|
16
|
+
};
|
|
17
|
+
var ObjHash = /*#__PURE__*/function () {
|
|
18
|
+
function ObjHash() {
|
|
19
|
+
_classCallCheck(this, ObjHash);
|
|
20
|
+
}
|
|
21
|
+
_createClass(ObjHash, null, [{
|
|
22
|
+
key: "getForNode",
|
|
23
|
+
value: function getForNode(node) {
|
|
24
|
+
if (this.caching.has(node)) {
|
|
25
|
+
return this.caching.get(node);
|
|
26
|
+
}
|
|
27
|
+
var uniqueId = uuid();
|
|
28
|
+
this.caching.set(node, uniqueId);
|
|
29
|
+
return uniqueId;
|
|
30
|
+
}
|
|
31
|
+
}]);
|
|
32
|
+
return ObjHash;
|
|
33
|
+
}();
|
|
34
|
+
_defineProperty(ObjHash, "caching", new WeakMap());
|
|
35
|
+
export var unmountDecorations = function unmountDecorations(selector) {
|
|
36
|
+
// Removing decorations manually instead of using native destroy function in prosemirror API
|
|
37
|
+
// as it was more responsive and causes less re-rendering
|
|
38
|
+
var decorationsToRemove = document.querySelectorAll("[".concat(selector, "=\"true\"]"));
|
|
39
|
+
decorationsToRemove.forEach(function (el) {
|
|
40
|
+
ReactDOM.unmountComponentAtNode(el);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import { createElement } from 'react';
|
|
3
|
+
import { bind } from 'bind-event-listener';
|
|
4
|
+
import ReactDOM from 'react-dom';
|
|
5
|
+
import uuid from 'uuid';
|
|
6
|
+
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
7
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
9
|
+
import { DragHandle } from '../ui/drag-handle';
|
|
10
|
+
import { TYPE_HANDLE_DEC, TYPE_NODE_DEC, unmountDecorations } from './decorations-common';
|
|
11
|
+
export var emptyParagraphNodeDecorations = function emptyParagraphNodeDecorations() {
|
|
12
|
+
var anchorName = "--node-anchor-paragraph-0";
|
|
13
|
+
var style = "anchor-name: ".concat(anchorName, "; margin-top: 0px;");
|
|
14
|
+
return Decoration.node(0, 2, _defineProperty({
|
|
15
|
+
style: style
|
|
16
|
+
}, 'data-drag-handler-anchor-name', anchorName), {
|
|
17
|
+
type: TYPE_NODE_DEC
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
export var findHandleDec = function findHandleDec(decorations, from, to) {
|
|
21
|
+
return decorations.find(from, to, function (spec) {
|
|
22
|
+
return spec.type === TYPE_HANDLE_DEC;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
export var dragHandleDecoration = function dragHandleDecoration(api, formatMessage, pos, anchorName, nodeType, handleOptions) {
|
|
26
|
+
unmountDecorations('data-blocks-drag-handle-container');
|
|
27
|
+
var unbind;
|
|
28
|
+
return Decoration.widget(pos, function (view, getPos) {
|
|
29
|
+
var element = document.createElement('span');
|
|
30
|
+
// Need to set it to inline to avoid text being split when merging two paragraphs
|
|
31
|
+
// platform_editor_element_dnd_nested_fix_patch_2 -> inline decoration causes focus issues when refocusing Editor into first line
|
|
32
|
+
element.style.display = fg('platform_editor_element_dnd_nested_fix_patch_2') ? 'block' : 'inline';
|
|
33
|
+
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
34
|
+
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
35
|
+
var isTopLevelNode = true;
|
|
36
|
+
if (editorExperiment('nested-dnd', true)) {
|
|
37
|
+
var newPos = fg('platform_editor_element_dnd_nested_fix_patch_3') ? getPos() : pos;
|
|
38
|
+
if (typeof newPos === 'number') {
|
|
39
|
+
var $pos = view.state.doc.resolve(newPos);
|
|
40
|
+
isTopLevelNode = ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
|
|
41
|
+
}
|
|
42
|
+
/*
|
|
43
|
+
* We disable mouseover event to fix flickering issue on hover
|
|
44
|
+
* However, the tooltip for nested drag handle is no long working.
|
|
45
|
+
*/
|
|
46
|
+
if (newPos === undefined || !isTopLevelNode) {
|
|
47
|
+
// This will also hide the tooltip.
|
|
48
|
+
unbind = bind(element, {
|
|
49
|
+
type: 'mouseover',
|
|
50
|
+
listener: function listener(e) {
|
|
51
|
+
e.stopPropagation();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// There are times when global clear: "both" styles are applied to this decoration causing jumpiness
|
|
58
|
+
// due to margins applied to other nodes eg. Headings
|
|
59
|
+
element.style.clear = 'unset';
|
|
60
|
+
ReactDOM.render( /*#__PURE__*/createElement(DragHandle, {
|
|
61
|
+
view: view,
|
|
62
|
+
api: api,
|
|
63
|
+
formatMessage: formatMessage,
|
|
64
|
+
getPos: getPos,
|
|
65
|
+
anchorName: anchorName,
|
|
66
|
+
nodeType: nodeType,
|
|
67
|
+
handleOptions: handleOptions,
|
|
68
|
+
isTopLevelNode: isTopLevelNode
|
|
69
|
+
}), element);
|
|
70
|
+
return element;
|
|
71
|
+
}, {
|
|
72
|
+
side: -1,
|
|
73
|
+
type: TYPE_HANDLE_DEC,
|
|
74
|
+
testid: "".concat(TYPE_HANDLE_DEC, "-").concat(uuid()),
|
|
75
|
+
destroy: function destroy() {
|
|
76
|
+
if (editorExperiment('nested-dnd', true)) {
|
|
77
|
+
unbind && unbind();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
};
|