@atlaskit/editor-plugin-block-controls 1.4.28 → 1.4.30
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.js +18 -3
- package/dist/cjs/pm-plugins/handle-mouse-over.js +35 -0
- package/dist/cjs/pm-plugins/main.js +72 -36
- package/dist/cjs/ui/drag-handle.js +44 -17
- package/dist/cjs/ui/drag-preview.js +4 -0
- package/dist/cjs/ui/drop-target.js +2 -1
- package/dist/cjs/ui/global-styles.js +25 -1
- package/dist/cjs/utils/getSelection.js +1 -1
- package/dist/es2019/pm-plugins/decorations.js +17 -2
- package/dist/es2019/pm-plugins/handle-mouse-over.js +30 -0
- package/dist/es2019/pm-plugins/main.js +63 -29
- package/dist/es2019/ui/drag-handle.js +40 -12
- package/dist/es2019/ui/drag-preview.js +4 -0
- package/dist/es2019/ui/drop-target.js +2 -1
- package/dist/es2019/ui/global-styles.js +25 -1
- package/dist/es2019/utils/getSelection.js +1 -1
- package/dist/esm/pm-plugins/decorations.js +18 -3
- package/dist/esm/pm-plugins/handle-mouse-over.js +29 -0
- package/dist/esm/pm-plugins/main.js +72 -36
- package/dist/esm/ui/drag-handle.js +44 -17
- package/dist/esm/ui/drag-preview.js +4 -0
- package/dist/esm/ui/drop-target.js +2 -1
- package/dist/esm/ui/global-styles.js +25 -1
- package/dist/esm/utils/getSelection.js +1 -1
- package/dist/types/pm-plugins/handle-mouse-over.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/handle-mouse-over.d.ts +4 -0
- package/package.json +5 -2
|
@@ -9,6 +9,7 @@ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-sc
|
|
|
9
9
|
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
10
10
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
11
11
|
import { dragHandleDecoration, dropTargetDecorations, mouseMoveWrapperDecorations, nodeDecorations } from './decorations';
|
|
12
|
+
import { handleMouseOver } from './handle-mouse-over';
|
|
12
13
|
export const key = new PluginKey('blockControls');
|
|
13
14
|
const destroyFn = api => {
|
|
14
15
|
const scrollable = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
@@ -83,7 +84,7 @@ export const createPlugin = api => {
|
|
|
83
84
|
return initialState;
|
|
84
85
|
},
|
|
85
86
|
apply(tr, currentState, oldState, newState) {
|
|
86
|
-
var _meta$activeNode, _meta$isDragging, _meta$editorHeight;
|
|
87
|
+
var _meta$activeNode, _meta$activeNode2, _meta$isDragging, _meta$editorHeight;
|
|
87
88
|
if (initialState.isDocSizeLimitEnabled && newState.doc.nodeSize > DRAG_AND_DROP_DOC_SIZE_LIMIT) {
|
|
88
89
|
return initialState;
|
|
89
90
|
}
|
|
@@ -113,21 +114,45 @@ export const createPlugin = api => {
|
|
|
113
114
|
}) => spec.id === 'drag-handle');
|
|
114
115
|
decorations = decorations.remove(oldHandle);
|
|
115
116
|
}
|
|
117
|
+
let isDecsMissing = false;
|
|
118
|
+
let isHandleMissing = false;
|
|
119
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
120
|
+
// Ensure decorations stay in sync when nodes are added or removed from the doc
|
|
121
|
+
isHandleMissing = !(meta !== null && meta !== void 0 && meta.activeNode) && !decorations.find().some(({
|
|
122
|
+
spec
|
|
123
|
+
}) => spec.id === 'drag-handle');
|
|
124
|
+
const decsLength = decorations.find().filter(({
|
|
125
|
+
spec
|
|
126
|
+
}) => spec.id !== 'drag-handle').length;
|
|
127
|
+
isDecsMissing = !isDragging && decsLength !== newState.doc.childCount;
|
|
128
|
+
}
|
|
116
129
|
|
|
117
130
|
// This is not targeted enough - it's trying to catch events like expand being set to breakout
|
|
118
131
|
const maybeWidthUpdated = tr.docChanged && oldState.doc.nodeSize === newState.doc.nodeSize && !nodeCountChanged;
|
|
119
|
-
|
|
132
|
+
|
|
133
|
+
// This addresses scenarios such as undoing table resizing,
|
|
134
|
+
// where a keyboard shortcut triggers a width change, and
|
|
135
|
+
// the node's actual width is then updated in a separate renderering cycle.
|
|
136
|
+
// The tr.meta.activeNode is triggered by the showDragHandleAt function during the mouse entry event
|
|
137
|
+
// (when the table node rerenders)
|
|
138
|
+
// The activeNode is from the previous rendering cycle, and verify if they share the same anchor.
|
|
139
|
+
const maybeNodeWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 ? void 0 : (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName);
|
|
140
|
+
const redrawDecorations = decorations === DecorationSet.empty || (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== editorHeight || maybeWidthUpdated || nodeCountChanged || maybeNodeWidthUpdated || resizerMeta === false || isDecsMissing || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
|
|
120
141
|
|
|
121
142
|
// Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
|
|
122
143
|
if (redrawDecorations && !isResizerResizing && api) {
|
|
123
144
|
decorations = DecorationSet.create(newState.doc, []);
|
|
124
145
|
const nodeDecs = nodeDecorations(newState);
|
|
125
|
-
|
|
126
|
-
|
|
146
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
147
|
+
decorations = decorations.add(newState.doc, [...nodeDecs]);
|
|
148
|
+
} else {
|
|
149
|
+
const mouseWrapperDecs = mouseMoveWrapperDecorations(newState, api);
|
|
150
|
+
decorations = decorations.add(newState.doc, [...nodeDecs, ...mouseWrapperDecs]);
|
|
151
|
+
}
|
|
127
152
|
|
|
128
153
|
// Note: Quite often the handle is not in the right position after a node is moved
|
|
129
154
|
// it is safer for now to not show it when a node is moved
|
|
130
|
-
if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved)) {
|
|
155
|
+
if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved) && !isDecsMissing) {
|
|
131
156
|
const newActiveNode = activeNode && tr.doc.nodeAt(tr.mapping.map(activeNode.pos));
|
|
132
157
|
let nodeType = activeNode.nodeType;
|
|
133
158
|
let anchorName = activeNode.anchorName;
|
|
@@ -197,7 +222,7 @@ export const createPlugin = api => {
|
|
|
197
222
|
return {
|
|
198
223
|
decorations,
|
|
199
224
|
decorationState,
|
|
200
|
-
activeNode: isEmptyDoc ? null : (_meta$
|
|
225
|
+
activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode2 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode2 !== void 0 ? _meta$activeNode2 : mappedActiveNodePos,
|
|
201
226
|
isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging,
|
|
202
227
|
isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
|
|
203
228
|
editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
|
|
@@ -236,41 +261,50 @@ export const createPlugin = api => {
|
|
|
236
261
|
return true;
|
|
237
262
|
}
|
|
238
263
|
return false;
|
|
264
|
+
},
|
|
265
|
+
mouseover: (view, event) => {
|
|
266
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
267
|
+
handleMouseOver(view, event, api);
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
239
270
|
}
|
|
240
271
|
}
|
|
241
272
|
},
|
|
242
273
|
view: editorView => {
|
|
243
274
|
const dom = editorView.dom;
|
|
275
|
+
let resizeObserver;
|
|
276
|
+
if (!getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
277
|
+
// Use ResizeObserver to observe height changes
|
|
278
|
+
resizeObserver = new ResizeObserver(rafSchedule(entries => {
|
|
279
|
+
const editorHeight = entries[0].contentBoxSize[0].blockSize;
|
|
244
280
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
editorHeight
|
|
260
|
-
});
|
|
281
|
+
// Update the plugin state when the height changes
|
|
282
|
+
const pluginState = key.getState(editorView.state);
|
|
283
|
+
if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDragging)) {
|
|
284
|
+
const isResizerResizing = !!dom.querySelector('.is-resizing');
|
|
285
|
+
const transaction = editorView.state.tr;
|
|
286
|
+
if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.isResizerResizing) !== isResizerResizing) {
|
|
287
|
+
transaction.setMeta('is-resizer-resizing', isResizerResizing);
|
|
288
|
+
}
|
|
289
|
+
if (!isResizerResizing) {
|
|
290
|
+
transaction.setMeta(key, {
|
|
291
|
+
editorHeight
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
editorView.dispatch(transaction);
|
|
261
295
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
// Start observing the editor DOM element
|
|
267
|
-
resizeObserver.observe(dom);
|
|
296
|
+
}));
|
|
297
|
+
// Start observing the editor DOM element
|
|
298
|
+
resizeObserver.observe(dom);
|
|
299
|
+
}
|
|
268
300
|
|
|
269
301
|
// Start pragmatic monitors
|
|
270
302
|
const pragmaticCleanup = destroyFn(api);
|
|
271
303
|
return {
|
|
272
304
|
destroy() {
|
|
273
|
-
|
|
305
|
+
if (!getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
306
|
+
resizeObserver.unobserve(dom);
|
|
307
|
+
}
|
|
274
308
|
pragmaticCleanup();
|
|
275
309
|
}
|
|
276
310
|
};
|
|
@@ -5,7 +5,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
5
5
|
import { css, jsx } from '@emotion/react';
|
|
6
6
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
7
7
|
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
8
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
9
|
import DragHandlerIcon from '@atlaskit/icon/glyph/drag-handler';
|
|
10
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
9
11
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
10
12
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
11
13
|
import { key } from '../pm-plugins/main';
|
|
@@ -74,7 +76,7 @@ export const DragHandle = ({
|
|
|
74
76
|
}
|
|
75
77
|
}, [anchorName, nodeType, view.dom]);
|
|
76
78
|
const handleOnClick = useCallback(() => {
|
|
77
|
-
var _api$core
|
|
79
|
+
var _api$core;
|
|
78
80
|
setDragHandleSelected(!dragHandleSelected);
|
|
79
81
|
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
80
82
|
tr
|
|
@@ -88,15 +90,15 @@ export const DragHandle = ({
|
|
|
88
90
|
});
|
|
89
91
|
return tr;
|
|
90
92
|
});
|
|
91
|
-
|
|
92
|
-
}, [start, api, dragHandleSelected, setDragHandleSelected, nodeType]);
|
|
93
|
+
view.focus();
|
|
94
|
+
}, [start, api, view, dragHandleSelected, setDragHandleSelected, nodeType]);
|
|
93
95
|
|
|
94
96
|
// handleMouseDown required along with onClick to ensure the correct selection
|
|
95
97
|
// is set immediately when the drag handle is clicked. Otherwise browser native
|
|
96
98
|
// drag and drop can take over and cause unpredictable behaviour.
|
|
97
99
|
const handleMouseDown = useCallback(() => {
|
|
98
|
-
var _api$
|
|
99
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
100
|
+
var _api$core2;
|
|
101
|
+
api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(({
|
|
100
102
|
tr
|
|
101
103
|
}) => {
|
|
102
104
|
if (start === undefined) {
|
|
@@ -108,8 +110,33 @@ export const DragHandle = ({
|
|
|
108
110
|
});
|
|
109
111
|
return tr;
|
|
110
112
|
});
|
|
111
|
-
|
|
112
|
-
}, [start, api, nodeType]);
|
|
113
|
+
view.focus();
|
|
114
|
+
}, [start, api, view, nodeType]);
|
|
115
|
+
|
|
116
|
+
// TODO - This needs to be investigated further. Drag preview generation is not always working
|
|
117
|
+
// as expected with a node selection. This workaround sets the selection to the node on mouseDown,
|
|
118
|
+
// but ensures the preview is generated correctly.
|
|
119
|
+
const handleMouseDownWrapperRemoved = useCallback(() => {
|
|
120
|
+
var _api$core3;
|
|
121
|
+
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
|
|
122
|
+
tr
|
|
123
|
+
}) => {
|
|
124
|
+
if (start === undefined) {
|
|
125
|
+
return tr;
|
|
126
|
+
}
|
|
127
|
+
const node = tr.doc.nodeAt(start);
|
|
128
|
+
if (!node) {
|
|
129
|
+
return tr;
|
|
130
|
+
}
|
|
131
|
+
const $startPos = tr.doc.resolve(start + node.nodeSize);
|
|
132
|
+
const selection = new TextSelection($startPos);
|
|
133
|
+
tr.setSelection(selection);
|
|
134
|
+
tr.setMeta(key, {
|
|
135
|
+
pos: start
|
|
136
|
+
});
|
|
137
|
+
return tr;
|
|
138
|
+
});
|
|
139
|
+
}, [start, api]);
|
|
113
140
|
useEffect(() => {
|
|
114
141
|
const element = buttonRef.current;
|
|
115
142
|
if (!element) {
|
|
@@ -138,11 +165,11 @@ export const DragHandle = ({
|
|
|
138
165
|
});
|
|
139
166
|
},
|
|
140
167
|
onDragStart() {
|
|
141
|
-
var _api$
|
|
168
|
+
var _api$core4;
|
|
142
169
|
if (start === undefined) {
|
|
143
170
|
return;
|
|
144
171
|
}
|
|
145
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
172
|
+
api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(({
|
|
146
173
|
tr
|
|
147
174
|
}) => {
|
|
148
175
|
var _api$blockControls, _api$analytics;
|
|
@@ -151,6 +178,7 @@ export const DragHandle = ({
|
|
|
151
178
|
});
|
|
152
179
|
const resolvedMovingNode = tr.doc.resolve(start);
|
|
153
180
|
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
181
|
+
tr.setMeta('scrollIntoView', false);
|
|
154
182
|
api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
|
|
155
183
|
eventType: EVENT_TYPE.UI,
|
|
156
184
|
action: ACTION.DRAGGED,
|
|
@@ -163,7 +191,7 @@ export const DragHandle = ({
|
|
|
163
191
|
})(tr);
|
|
164
192
|
return tr;
|
|
165
193
|
});
|
|
166
|
-
|
|
194
|
+
view.focus();
|
|
167
195
|
}
|
|
168
196
|
});
|
|
169
197
|
}, [anchorName, api, nodeType, view, start]);
|
|
@@ -190,7 +218,7 @@ export const DragHandle = ({
|
|
|
190
218
|
}
|
|
191
219
|
if (supportsAnchor) {
|
|
192
220
|
return {
|
|
193
|
-
left: hasResizer || isExtension || isBlockCard || isEmbedCard ? getLeftPosition(dom, nodeType, innerContainer, macroInteractionUpdates) : `calc(anchor(${anchorName} start) - ${DRAG_HANDLE_WIDTH}px - ${dragHandleGap(nodeType)}px)`,
|
|
221
|
+
left: hasResizer || isExtension || isBlockCard || isEmbedCard ? getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? `calc(calc(anchor(${anchorName} start) + ${getLeftPosition(dom, nodeType, innerContainer, macroInteractionUpdates)}` : getLeftPosition(dom, nodeType, innerContainer, macroInteractionUpdates) : `calc(anchor(${anchorName} start) - ${DRAG_HANDLE_WIDTH}px - ${dragHandleGap(nodeType)}px)`,
|
|
194
222
|
top: anchorName.includes('table') ? `calc(anchor(${anchorName} start) + ${DRAG_HANDLE_HEIGHT}px)` : `anchor(${anchorName} start)`
|
|
195
223
|
};
|
|
196
224
|
}
|
|
@@ -207,7 +235,7 @@ export const DragHandle = ({
|
|
|
207
235
|
,
|
|
208
236
|
style: positionStyles,
|
|
209
237
|
onClick: handleOnClick,
|
|
210
|
-
onMouseDown: handleMouseDown,
|
|
238
|
+
onMouseDown: getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') ? handleMouseDownWrapperRemoved : handleMouseDown,
|
|
211
239
|
"data-testid": "block-ctrl-drag-handle"
|
|
212
240
|
}, jsx(DragHandlerIcon, {
|
|
213
241
|
label: "",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
1
2
|
import { B200 } from '@atlaskit/theme/colors';
|
|
2
3
|
const previewStyle = {
|
|
3
4
|
borderColor: `var(--ds-border-focused, ${B200})`,
|
|
@@ -14,6 +15,9 @@ export const dragPreview = (container, dom, nodeType) => {
|
|
|
14
15
|
const parent = document.createElement('div');
|
|
15
16
|
// ProseMirror class is required to make sure the cloned dom is styled correctly
|
|
16
17
|
parent.classList.add('ProseMirror');
|
|
18
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
19
|
+
parent.classList.add('block-ctrl-drag-preview');
|
|
20
|
+
}
|
|
17
21
|
const shouldBeGenericPreview = nodeType === 'embedCard' || nodeType === 'extension';
|
|
18
22
|
const embedCard = dom.querySelector('.embedCardView-content-wrap');
|
|
19
23
|
if (shouldBeGenericPreview || embedCard) {
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
2
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles, @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
3
3
|
import { css, Global, jsx } from '@emotion/react';
|
|
4
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
5
|
+
const extendedHoverZone = css({
|
|
6
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
7
|
+
'.block-ctrl-drag-preview [data-drag-handler-anchor-name]::after': {
|
|
8
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
|
|
9
|
+
display: 'none !important'
|
|
10
|
+
},
|
|
11
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
12
|
+
'[data-drag-handler-anchor-name]::after': {
|
|
13
|
+
content: '""',
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
top: 0,
|
|
16
|
+
left: '-100%',
|
|
17
|
+
width: '100%',
|
|
18
|
+
height: '100%',
|
|
19
|
+
background: 'transparent',
|
|
20
|
+
cursor: 'default',
|
|
21
|
+
zIndex: -1
|
|
22
|
+
},
|
|
23
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
|
|
24
|
+
'[data-blocks-decoration-container="true"] + *::after': {
|
|
25
|
+
display: 'none'
|
|
26
|
+
}
|
|
27
|
+
});
|
|
4
28
|
const globalStyles = css({
|
|
5
29
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
|
|
6
30
|
'.ProseMirror-widget:first-child + *': {
|
|
@@ -10,6 +34,6 @@ const globalStyles = css({
|
|
|
10
34
|
});
|
|
11
35
|
export const GlobalStylesWrapper = () => {
|
|
12
36
|
return jsx(Global, {
|
|
13
|
-
styles: globalStyles
|
|
37
|
+
styles: [globalStyles, getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2') && extendedHoverZone]
|
|
14
38
|
});
|
|
15
39
|
};
|
|
@@ -26,7 +26,7 @@ export const getSelection = (tr, start) => {
|
|
|
26
26
|
return true;
|
|
27
27
|
});
|
|
28
28
|
const inlineNodeDepth = inlineNodePos - start;
|
|
29
|
-
return new TextSelection(tr.doc.resolve(
|
|
29
|
+
return new TextSelection(tr.doc.resolve(start + nodeSize - inlineNodeDepth), tr.doc.resolve(inlineNodePos));
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
export const selectNode = (tr, start, nodeType) => {
|
|
@@ -2,6 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
import { createElement } from 'react';
|
|
3
3
|
import ReactDOM from 'react-dom';
|
|
4
4
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
5
6
|
import { DragHandle } from '../ui/drag-handle';
|
|
6
7
|
import { DropTarget } from '../ui/drop-target';
|
|
7
8
|
import { MouseMoveWrapper } from '../ui/mouse-move-wrapper';
|
|
@@ -19,6 +20,9 @@ export var dropTargetDecorations = function dropTargetDecorations(oldState, newS
|
|
|
19
20
|
decs.push(Decoration.widget(pos, function () {
|
|
20
21
|
var element = document.createElement('div');
|
|
21
22
|
element.setAttribute('data-blocks-drop-target-container', 'true');
|
|
23
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
24
|
+
element.style.clear = 'unset';
|
|
25
|
+
}
|
|
22
26
|
ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
|
|
23
27
|
api: api,
|
|
24
28
|
index: index
|
|
@@ -61,11 +65,17 @@ export var dropTargetDecorations = function dropTargetDecorations(oldState, newS
|
|
|
61
65
|
export var nodeDecorations = function nodeDecorations(newState) {
|
|
62
66
|
var decs = [];
|
|
63
67
|
newState.doc.descendants(function (node, pos, _parent, index) {
|
|
68
|
+
var _Decoration$node;
|
|
64
69
|
var anchorName = "--node-anchor-".concat(node.type.name, "-").concat(index);
|
|
65
|
-
var style
|
|
66
|
-
|
|
70
|
+
var style;
|
|
71
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
72
|
+
style = "anchor-name: ".concat(anchorName, "; ").concat(pos === 0 ? 'margin-top: 0px;' : '', "; position: relative; z-index: 1;");
|
|
73
|
+
} else {
|
|
74
|
+
style = "anchor-name: ".concat(anchorName, "; ").concat(pos === 0 ? 'margin-top: 0px;' : '');
|
|
75
|
+
}
|
|
76
|
+
decs.push(Decoration.node(pos, pos + node.nodeSize, (_Decoration$node = {
|
|
67
77
|
style: style
|
|
68
|
-
}, 'data-drag-handler-anchor-name', anchorName)));
|
|
78
|
+
}, _defineProperty(_Decoration$node, 'data-drag-handler-anchor-name', anchorName), _defineProperty(_Decoration$node, 'data-drag-handler-node-type', node.type.name), _Decoration$node)));
|
|
69
79
|
return false;
|
|
70
80
|
});
|
|
71
81
|
return decs;
|
|
@@ -110,6 +120,11 @@ export var dragHandleDecoration = function dragHandleDecoration(pos, anchorName,
|
|
|
110
120
|
element.style.display = 'inline';
|
|
111
121
|
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
112
122
|
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
123
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
124
|
+
// There are times when global clear: "both" styles are applied to this decoration causing jumpiness
|
|
125
|
+
// due to margins applied to other nodes eg. Headings
|
|
126
|
+
element.style.clear = 'unset';
|
|
127
|
+
}
|
|
113
128
|
ReactDOM.render( /*#__PURE__*/createElement(DragHandle, {
|
|
114
129
|
view: view,
|
|
115
130
|
api: api,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export var handleMouseOver = function handleMouseOver(view, event, api) {
|
|
2
|
+
var _api$blockControls;
|
|
3
|
+
var _ref = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
|
|
4
|
+
isDragging = _ref.isDragging,
|
|
5
|
+
activeNode = _ref.activeNode;
|
|
6
|
+
// Most mouseover events don't fire during drag but some can slip through
|
|
7
|
+
// when the drag begins. This prevents those.
|
|
8
|
+
if (isDragging) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
var target = event.target;
|
|
12
|
+
if (target.classList.contains('ProseMirror')) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
var rootElement = target === null || target === void 0 ? void 0 : target.closest('[data-drag-handler-anchor-name]');
|
|
16
|
+
if (rootElement) {
|
|
17
|
+
var anchorName = rootElement.getAttribute('data-drag-handler-anchor-name');
|
|
18
|
+
if ((activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName) === anchorName) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
var pos = view.posAtDOM(rootElement, 0, 0);
|
|
22
|
+
var rootPos = view.state.doc.resolve(pos).start(1) - 1;
|
|
23
|
+
var nodeType = rootElement.getAttribute('data-drag-handler-node-type');
|
|
24
|
+
if (nodeType) {
|
|
25
|
+
var _api$core, _api$blockControls2;
|
|
26
|
+
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.showDragHandleAt(rootPos, anchorName, nodeType));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -10,6 +10,7 @@ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-sc
|
|
|
10
10
|
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
11
11
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
12
12
|
import { dragHandleDecoration, dropTargetDecorations, mouseMoveWrapperDecorations, nodeDecorations } from './decorations';
|
|
13
|
+
import { handleMouseOver } from './handle-mouse-over';
|
|
13
14
|
export var key = new PluginKey('blockControls');
|
|
14
15
|
var destroyFn = function destroyFn(api) {
|
|
15
16
|
var scrollable = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
@@ -82,7 +83,7 @@ export var createPlugin = function createPlugin(api) {
|
|
|
82
83
|
return initialState;
|
|
83
84
|
},
|
|
84
85
|
apply: function apply(tr, currentState, oldState, newState) {
|
|
85
|
-
var _meta$activeNode, _meta$isDragging, _meta$editorHeight;
|
|
86
|
+
var _meta$activeNode, _meta$activeNode2, _meta$isDragging, _meta$editorHeight;
|
|
86
87
|
if (initialState.isDocSizeLimitEnabled && newState.doc.nodeSize > DRAG_AND_DROP_DOC_SIZE_LIMIT) {
|
|
87
88
|
return initialState;
|
|
88
89
|
}
|
|
@@ -113,21 +114,47 @@ export var createPlugin = function createPlugin(api) {
|
|
|
113
114
|
});
|
|
114
115
|
decorations = decorations.remove(oldHandle);
|
|
115
116
|
}
|
|
117
|
+
var isDecsMissing = false;
|
|
118
|
+
var isHandleMissing = false;
|
|
119
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
120
|
+
// Ensure decorations stay in sync when nodes are added or removed from the doc
|
|
121
|
+
isHandleMissing = !(meta !== null && meta !== void 0 && meta.activeNode) && !decorations.find().some(function (_ref6) {
|
|
122
|
+
var spec = _ref6.spec;
|
|
123
|
+
return spec.id === 'drag-handle';
|
|
124
|
+
});
|
|
125
|
+
var decsLength = decorations.find().filter(function (_ref7) {
|
|
126
|
+
var spec = _ref7.spec;
|
|
127
|
+
return spec.id !== 'drag-handle';
|
|
128
|
+
}).length;
|
|
129
|
+
isDecsMissing = !isDragging && decsLength !== newState.doc.childCount;
|
|
130
|
+
}
|
|
116
131
|
|
|
117
132
|
// This is not targeted enough - it's trying to catch events like expand being set to breakout
|
|
118
133
|
var maybeWidthUpdated = tr.docChanged && oldState.doc.nodeSize === newState.doc.nodeSize && !nodeCountChanged;
|
|
119
|
-
|
|
134
|
+
|
|
135
|
+
// This addresses scenarios such as undoing table resizing,
|
|
136
|
+
// where a keyboard shortcut triggers a width change, and
|
|
137
|
+
// the node's actual width is then updated in a separate renderering cycle.
|
|
138
|
+
// The tr.meta.activeNode is triggered by the showDragHandleAt function during the mouse entry event
|
|
139
|
+
// (when the table node rerenders)
|
|
140
|
+
// The activeNode is from the previous rendering cycle, and verify if they share the same anchor.
|
|
141
|
+
var maybeNodeWidthUpdated = (meta === null || meta === void 0 ? void 0 : meta.activeNode) && (meta === null || meta === void 0 || (_meta$activeNode = meta.activeNode) === null || _meta$activeNode === void 0 ? void 0 : _meta$activeNode.nodeType) === 'table' && meta.activeNode.anchorName === (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName);
|
|
142
|
+
var redrawDecorations = decorations === DecorationSet.empty || (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== editorHeight || maybeWidthUpdated || nodeCountChanged || maybeNodeWidthUpdated || resizerMeta === false || isDecsMissing || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
|
|
120
143
|
|
|
121
144
|
// Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
|
|
122
145
|
if (redrawDecorations && !isResizerResizing && api) {
|
|
123
146
|
decorations = DecorationSet.create(newState.doc, []);
|
|
124
147
|
var nodeDecs = nodeDecorations(newState);
|
|
125
|
-
|
|
126
|
-
|
|
148
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
149
|
+
decorations = decorations.add(newState.doc, _toConsumableArray(nodeDecs));
|
|
150
|
+
} else {
|
|
151
|
+
var mouseWrapperDecs = mouseMoveWrapperDecorations(newState, api);
|
|
152
|
+
decorations = decorations.add(newState.doc, [].concat(_toConsumableArray(nodeDecs), _toConsumableArray(mouseWrapperDecs)));
|
|
153
|
+
}
|
|
127
154
|
|
|
128
155
|
// Note: Quite often the handle is not in the right position after a node is moved
|
|
129
156
|
// it is safer for now to not show it when a node is moved
|
|
130
|
-
if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved)) {
|
|
157
|
+
if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved) && !isDecsMissing) {
|
|
131
158
|
var newActiveNode = activeNode && tr.doc.nodeAt(tr.mapping.map(activeNode.pos));
|
|
132
159
|
var nodeType = activeNode.nodeType;
|
|
133
160
|
var anchorName = activeNode.anchorName;
|
|
@@ -142,8 +169,8 @@ export var createPlugin = function createPlugin(api) {
|
|
|
142
169
|
|
|
143
170
|
// Remove previous drag handle widget and draw new drag handle widget when activeNode changes
|
|
144
171
|
if (meta !== null && meta !== void 0 && meta.activeNode && (meta === null || meta === void 0 ? void 0 : meta.activeNode.pos) !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos) && (meta === null || meta === void 0 ? void 0 : meta.activeNode.anchorName) !== (activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName) && api) {
|
|
145
|
-
var _oldHandle = decorations.find().filter(function (
|
|
146
|
-
var spec =
|
|
172
|
+
var _oldHandle = decorations.find().filter(function (_ref8) {
|
|
173
|
+
var spec = _ref8.spec;
|
|
147
174
|
return spec.id === 'drag-handle';
|
|
148
175
|
});
|
|
149
176
|
decorations = decorations.remove(_oldHandle);
|
|
@@ -163,8 +190,8 @@ export var createPlugin = function createPlugin(api) {
|
|
|
163
190
|
|
|
164
191
|
// Remove drop target decoration when dragging stops
|
|
165
192
|
if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false && !tr.docChanged) {
|
|
166
|
-
var dropTargetDecs = decorations.find().filter(function (
|
|
167
|
-
var spec =
|
|
193
|
+
var dropTargetDecs = decorations.find().filter(function (_ref9) {
|
|
194
|
+
var spec = _ref9.spec;
|
|
168
195
|
return spec.type === 'drop-target-decoration';
|
|
169
196
|
});
|
|
170
197
|
decorations = decorations.remove(dropTargetDecs);
|
|
@@ -172,9 +199,9 @@ export var createPlugin = function createPlugin(api) {
|
|
|
172
199
|
|
|
173
200
|
// Map drop target decoration positions when the document changes
|
|
174
201
|
if (tr.docChanged && isDragging) {
|
|
175
|
-
decorationState = decorationState.map(function (
|
|
176
|
-
var index =
|
|
177
|
-
pos =
|
|
202
|
+
decorationState = decorationState.map(function (_ref10) {
|
|
203
|
+
var index = _ref10.index,
|
|
204
|
+
pos = _ref10.pos;
|
|
178
205
|
return {
|
|
179
206
|
index: index,
|
|
180
207
|
pos: tr.mapping.map(pos)
|
|
@@ -197,7 +224,7 @@ export var createPlugin = function createPlugin(api) {
|
|
|
197
224
|
return {
|
|
198
225
|
decorations: decorations,
|
|
199
226
|
decorationState: decorationState,
|
|
200
|
-
activeNode: isEmptyDoc ? null : (_meta$
|
|
227
|
+
activeNode: isEmptyDoc || isHandleMissing ? null : (_meta$activeNode2 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode2 !== void 0 ? _meta$activeNode2 : mappedActiveNodePos,
|
|
201
228
|
isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging,
|
|
202
229
|
isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
|
|
203
230
|
editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
|
|
@@ -234,41 +261,50 @@ export var createPlugin = function createPlugin(api) {
|
|
|
234
261
|
return true;
|
|
235
262
|
}
|
|
236
263
|
return false;
|
|
264
|
+
},
|
|
265
|
+
mouseover: function mouseover(view, event) {
|
|
266
|
+
if (getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
267
|
+
handleMouseOver(view, event, api);
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
237
270
|
}
|
|
238
271
|
}
|
|
239
272
|
},
|
|
240
273
|
view: function view(editorView) {
|
|
241
274
|
var dom = editorView.dom;
|
|
275
|
+
var resizeObserver;
|
|
276
|
+
if (!getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
277
|
+
// Use ResizeObserver to observe height changes
|
|
278
|
+
resizeObserver = new ResizeObserver(rafSchedule(function (entries) {
|
|
279
|
+
var editorHeight = entries[0].contentBoxSize[0].blockSize;
|
|
242
280
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
editorHeight: editorHeight
|
|
258
|
-
});
|
|
281
|
+
// Update the plugin state when the height changes
|
|
282
|
+
var pluginState = key.getState(editorView.state);
|
|
283
|
+
if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDragging)) {
|
|
284
|
+
var isResizerResizing = !!dom.querySelector('.is-resizing');
|
|
285
|
+
var transaction = editorView.state.tr;
|
|
286
|
+
if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.isResizerResizing) !== isResizerResizing) {
|
|
287
|
+
transaction.setMeta('is-resizer-resizing', isResizerResizing);
|
|
288
|
+
}
|
|
289
|
+
if (!isResizerResizing) {
|
|
290
|
+
transaction.setMeta(key, {
|
|
291
|
+
editorHeight: editorHeight
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
editorView.dispatch(transaction);
|
|
259
295
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
// Start observing the editor DOM element
|
|
265
|
-
resizeObserver.observe(dom);
|
|
296
|
+
}));
|
|
297
|
+
// Start observing the editor DOM element
|
|
298
|
+
resizeObserver.observe(dom);
|
|
299
|
+
}
|
|
266
300
|
|
|
267
301
|
// Start pragmatic monitors
|
|
268
302
|
var pragmaticCleanup = destroyFn(api);
|
|
269
303
|
return {
|
|
270
304
|
destroy: function destroy() {
|
|
271
|
-
|
|
305
|
+
if (!getBooleanFF('platform.editor.elements.drag-and-drop-remove-wrapper_fyqr2')) {
|
|
306
|
+
resizeObserver.unobserve(dom);
|
|
307
|
+
}
|
|
272
308
|
pragmaticCleanup();
|
|
273
309
|
}
|
|
274
310
|
};
|