@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.
Files changed (36) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/pm-plugins/decorations-anchor.js +97 -0
  3. package/dist/cjs/pm-plugins/decorations-common.js +49 -0
  4. package/dist/cjs/pm-plugins/decorations-drag-handle.js +88 -0
  5. package/dist/cjs/pm-plugins/{decorations.js → decorations-drop-target.js} +11 -209
  6. package/dist/cjs/pm-plugins/main.js +21 -19
  7. package/dist/cjs/ui/drop-target-v2.js +3 -3
  8. package/dist/cjs/ui/global-styles.js +101 -86
  9. package/dist/cjs/ui/inline-drop-target.js +3 -3
  10. package/dist/es2019/pm-plugins/decorations-anchor.js +89 -0
  11. package/dist/es2019/pm-plugins/decorations-common.js +31 -0
  12. package/dist/es2019/pm-plugins/decorations-drag-handle.js +79 -0
  13. package/dist/es2019/pm-plugins/{decorations.js → decorations-drop-target.js} +6 -193
  14. package/dist/es2019/pm-plugins/main.js +3 -1
  15. package/dist/es2019/ui/drop-target-v2.js +1 -1
  16. package/dist/es2019/ui/global-styles.js +17 -6
  17. package/dist/es2019/ui/inline-drop-target.js +1 -1
  18. package/dist/esm/pm-plugins/decorations-anchor.js +90 -0
  19. package/dist/esm/pm-plugins/decorations-common.js +42 -0
  20. package/dist/esm/pm-plugins/decorations-drag-handle.js +81 -0
  21. package/dist/esm/pm-plugins/{decorations.js → decorations-drop-target.js} +6 -204
  22. package/dist/esm/pm-plugins/main.js +3 -1
  23. package/dist/esm/ui/drop-target-v2.js +1 -1
  24. package/dist/esm/ui/global-styles.js +101 -86
  25. package/dist/esm/ui/inline-drop-target.js +1 -1
  26. package/dist/types/pm-plugins/decorations-anchor.d.ts +13 -0
  27. package/dist/types/pm-plugins/decorations-common.d.ts +7 -0
  28. package/dist/types/pm-plugins/decorations-drag-handle.d.ts +7 -0
  29. package/dist/types/pm-plugins/decorations-drop-target.d.ts +17 -0
  30. package/dist/types-ts4.5/pm-plugins/decorations-anchor.d.ts +13 -0
  31. package/dist/types-ts4.5/pm-plugins/decorations-common.d.ts +7 -0
  32. package/dist/types-ts4.5/pm-plugins/decorations-drag-handle.d.ts +7 -0
  33. package/dist/types-ts4.5/pm-plugins/decorations-drop-target.d.ts +17 -0
  34. package/package.json +4 -4
  35. package/dist/types/pm-plugins/decorations.d.ts +0 -35
  36. 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
- export const TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
21
- export const TYPE_HANDLE_DEC = 'drag-handle';
22
- export const TYPE_NODE_DEC = 'node-decoration';
23
- const getNestedDepth = () => editorExperiment('nested-dnd', true) ? 100 : 0;
24
- export const getNodeAnchor = node => {
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 { dragHandleDecoration, dropTargetDecorations, emptyParagraphNodeDecorations, findDropTargetDecs, findHandleDec, findNodeDecs, nodeDecorations } from './decorations';
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
- zIndex: -1
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
- zIndex: -1
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
+ };