@atlaskit/editor-plugin-block-controls 1.4.20 → 1.4.22
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 -1
- package/dist/cjs/pm-plugins/main.js +54 -29
- package/dist/cjs/ui/drag-handle.js +0 -9
- package/dist/cjs/ui/drop-target.js +2 -16
- package/dist/cjs/ui/mouse-move-wrapper.js +31 -28
- package/dist/es2019/pm-plugins/decorations.js +18 -1
- package/dist/es2019/pm-plugins/main.js +43 -17
- package/dist/es2019/ui/drag-handle.js +0 -10
- package/dist/es2019/ui/drop-target.js +2 -16
- package/dist/es2019/ui/mouse-move-wrapper.js +26 -20
- package/dist/esm/pm-plugins/decorations.js +18 -1
- package/dist/esm/pm-plugins/main.js +54 -29
- package/dist/esm/ui/drag-handle.js +0 -9
- package/dist/esm/ui/drop-target.js +2 -16
- package/dist/esm/ui/mouse-move-wrapper.js +31 -28
- package/dist/types/index.d.ts +1 -1
- package/dist/types/pm-plugins/main.d.ts +11 -1
- package/dist/types/types.d.ts +10 -9
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/main.d.ts +11 -1
- package/dist/types-ts4.5/types.d.ts +10 -9
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-controls
|
|
2
2
|
|
|
3
|
+
## 1.4.22
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#111855](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/111855)
|
|
8
|
+
[`858997cc1d1e0`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/858997cc1d1e0) -
|
|
9
|
+
ED-23619 Improve drop latency by cleaning up decorations before they are being redrawn
|
|
10
|
+
|
|
11
|
+
## 1.4.21
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#111695](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/111695)
|
|
16
|
+
[`4dadac69832d7`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/4dadac69832d7) -
|
|
17
|
+
Refactor Pragmatic usage
|
|
18
|
+
- [#111695](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/111695)
|
|
19
|
+
[`c8e7bf89f5bd8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c8e7bf89f5bd8) -
|
|
20
|
+
reduce rerenders in mousemovewrapper
|
|
21
|
+
|
|
3
22
|
## 1.4.20
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -14,6 +14,7 @@ var _dropTarget = require("../ui/drop-target");
|
|
|
14
14
|
var _mouseMoveWrapper = require("../ui/mouse-move-wrapper");
|
|
15
15
|
var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetDecorations(oldState, newState, api) {
|
|
16
16
|
var decs = [];
|
|
17
|
+
unmountDecorations('data-blocks-drop-target-container');
|
|
17
18
|
// Decoration state is used to keep track of the position of the drop targets
|
|
18
19
|
// and allows us to easily map the updated position in the plugin apply method.
|
|
19
20
|
var decorationState = [];
|
|
@@ -24,6 +25,7 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
|
|
|
24
25
|
});
|
|
25
26
|
decs.push(_view.Decoration.widget(pos, function () {
|
|
26
27
|
var element = document.createElement('div');
|
|
28
|
+
element.setAttribute('data-blocks-drop-target-container', 'true');
|
|
27
29
|
_reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_dropTarget.DropTarget, {
|
|
28
30
|
api: api,
|
|
29
31
|
index: index
|
|
@@ -48,6 +50,7 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
|
|
|
48
50
|
});
|
|
49
51
|
decs.push(_view.Decoration.widget(newState.doc.nodeSize - 2, function () {
|
|
50
52
|
var element = document.createElement('div');
|
|
53
|
+
element.setAttribute('data-blocks-drop-target-container', 'true');
|
|
51
54
|
_reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_dropTarget.DropTarget, {
|
|
52
55
|
api: api,
|
|
53
56
|
index: decorationState.length
|
|
@@ -80,10 +83,12 @@ var nodeDecorations = exports.nodeDecorations = function nodeDecorations(newStat
|
|
|
80
83
|
*/
|
|
81
84
|
var mouseMoveWrapperDecorations = exports.mouseMoveWrapperDecorations = function mouseMoveWrapperDecorations(newState, api) {
|
|
82
85
|
var decs = [];
|
|
86
|
+
unmountDecorations('data-blocks-decoration-container');
|
|
83
87
|
newState.doc.descendants(function (node, pos, _parent, index) {
|
|
84
88
|
var anchorName = "--node-anchor-".concat(node.type.name, "-").concat(index);
|
|
85
89
|
decs.push(_view.Decoration.widget(pos, function (view, getPos) {
|
|
86
90
|
var element = document.createElement('div');
|
|
91
|
+
element.setAttribute('data-blocks-decoration-container', 'true');
|
|
87
92
|
_reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_mouseMoveWrapper.MouseMoveWrapper, {
|
|
88
93
|
view: view,
|
|
89
94
|
api: api,
|
|
@@ -108,6 +113,7 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
|
|
|
108
113
|
return _view.Decoration.widget(pos, function (view, getPos) {
|
|
109
114
|
var element = document.createElement('div');
|
|
110
115
|
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
116
|
+
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
111
117
|
_reactDom.default.render( /*#__PURE__*/(0, _react.createElement)(_dragHandle.DragHandle, {
|
|
112
118
|
view: view,
|
|
113
119
|
api: api,
|
|
@@ -118,6 +124,17 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
|
|
|
118
124
|
return element;
|
|
119
125
|
}, {
|
|
120
126
|
side: -1,
|
|
121
|
-
id: 'drag-handle'
|
|
127
|
+
id: 'drag-handle',
|
|
128
|
+
destroy: function destroy(node) {
|
|
129
|
+
_reactDom.default.unmountComponentAtNode(node);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
var unmountDecorations = function unmountDecorations(selector) {
|
|
134
|
+
// Removing decorations manually instead of using native destroy function in prosemirror API
|
|
135
|
+
// as it was more responsive and causes less re-rendering
|
|
136
|
+
var decorationsToRemove = document.querySelectorAll("[".concat(selector, "=\"true\"]"));
|
|
137
|
+
decorationsToRemove.forEach(function (el) {
|
|
138
|
+
_reactDom.default.unmountComponentAtNode(el);
|
|
122
139
|
});
|
|
123
140
|
};
|
|
@@ -12,26 +12,46 @@ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
|
12
12
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
13
13
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
14
14
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
15
|
+
var _element = require("@atlaskit/pragmatic-drag-and-drop-auto-scroll/element");
|
|
16
|
+
var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
|
|
15
17
|
var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
|
|
16
18
|
var _decorations = require("./decorations");
|
|
17
19
|
var key = exports.key = new _state.PluginKey('blockControls');
|
|
18
20
|
var destroyFn = function destroyFn(api) {
|
|
19
|
-
|
|
21
|
+
var scrollable = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
22
|
+
var cleanupFn = [];
|
|
23
|
+
if (scrollable) {
|
|
24
|
+
cleanupFn.push((0, _element.autoScrollForElements)({
|
|
25
|
+
element: scrollable
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
cleanupFn.push((0, _adapter.monitorForElements)({
|
|
20
29
|
canMonitor: function canMonitor(_ref) {
|
|
21
30
|
var source = _ref.source;
|
|
22
31
|
return source.data.type === 'element';
|
|
23
32
|
},
|
|
33
|
+
onDragStart: function onDragStart() {
|
|
34
|
+
scrollable.style.setProperty('scroll-behavior', 'unset');
|
|
35
|
+
},
|
|
24
36
|
onDrop: function onDrop(_ref2) {
|
|
37
|
+
var _api$core;
|
|
25
38
|
var location = _ref2.location,
|
|
26
39
|
source = _ref2.source;
|
|
40
|
+
scrollable.style.setProperty('scroll-behavior', null);
|
|
41
|
+
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref3) {
|
|
42
|
+
var tr = _ref3.tr;
|
|
43
|
+
return tr.setMeta(key, {
|
|
44
|
+
isDragging: false
|
|
45
|
+
});
|
|
46
|
+
});
|
|
27
47
|
// if no drop targets are rendered, assume that drop is invalid
|
|
28
48
|
if (location.current.dropTargets.length === 0) {
|
|
29
|
-
var _api$
|
|
30
|
-
var
|
|
31
|
-
start =
|
|
32
|
-
api === null || api === void 0 || (_api$
|
|
49
|
+
var _api$core2;
|
|
50
|
+
var _ref4 = source.data,
|
|
51
|
+
start = _ref4.start;
|
|
52
|
+
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref5) {
|
|
33
53
|
var _api$analytics;
|
|
34
|
-
var tr =
|
|
54
|
+
var tr = _ref5.tr;
|
|
35
55
|
var resolvedMovingNode = tr.doc.resolve(start);
|
|
36
56
|
var maybeNode = resolvedMovingNode.nodeAfter;
|
|
37
57
|
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
|
|
@@ -48,7 +68,8 @@ var destroyFn = function destroyFn(api) {
|
|
|
48
68
|
});
|
|
49
69
|
}
|
|
50
70
|
}
|
|
51
|
-
});
|
|
71
|
+
}));
|
|
72
|
+
return _combine.combine.apply(void 0, cleanupFn);
|
|
52
73
|
};
|
|
53
74
|
var initialState = {
|
|
54
75
|
decorations: _view.DecorationSet.empty,
|
|
@@ -56,8 +77,6 @@ var initialState = {
|
|
|
56
77
|
activeNode: null,
|
|
57
78
|
isDragging: false,
|
|
58
79
|
isMenuOpen: false,
|
|
59
|
-
start: null,
|
|
60
|
-
end: null,
|
|
61
80
|
editorHeight: 0,
|
|
62
81
|
isResizerResizing: false,
|
|
63
82
|
isDocSizeLimitEnabled: false
|
|
@@ -74,7 +93,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
74
93
|
return initialState;
|
|
75
94
|
},
|
|
76
95
|
apply: function apply(tr, currentState, oldState, newState) {
|
|
77
|
-
var _decorationState, _meta$activeNode, _meta$isDragging, _meta$editorHeight
|
|
96
|
+
var _decorationState, _meta$activeNode, _meta$isDragging, _meta$editorHeight;
|
|
78
97
|
if (initialState.isDocSizeLimitEnabled && newState.doc.nodeSize > DRAG_AND_DROP_DOC_SIZE_LIMIT) {
|
|
79
98
|
return initialState;
|
|
80
99
|
}
|
|
@@ -89,29 +108,31 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
89
108
|
// If tables or media are being resized, we want to hide the drag handle
|
|
90
109
|
var resizerMeta = tr.getMeta('is-resizer-resizing');
|
|
91
110
|
isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
|
|
92
|
-
var isEmptyDoc = newState.doc.childCount === 1 && newState.doc.nodeSize <= 4;
|
|
93
|
-
|
|
94
|
-
// This is not targeted enough - it's trying to catch events like expand being set to breakout
|
|
95
|
-
var maybeWidthUpdated = tr.docChanged && oldState.doc.nodeSize === newState.doc.nodeSize && oldState.doc.childCount === newState.doc.childCount;
|
|
96
111
|
var nodeCountChanged = oldState.doc.childCount !== newState.doc.childCount;
|
|
97
112
|
|
|
98
113
|
// During resize, remove the drag handle widget
|
|
99
|
-
if (isResizerResizing || nodeCountChanged) {
|
|
100
|
-
var oldHandle = decorations.find().filter(function (
|
|
101
|
-
var spec =
|
|
114
|
+
if (isResizerResizing || nodeCountChanged || meta !== null && meta !== void 0 && meta.nodeMoved) {
|
|
115
|
+
var oldHandle = decorations.find().filter(function (_ref6) {
|
|
116
|
+
var spec = _ref6.spec;
|
|
102
117
|
return spec.id === 'drag-handle';
|
|
103
118
|
});
|
|
104
119
|
decorations = decorations.remove(oldHandle);
|
|
105
120
|
}
|
|
106
121
|
|
|
122
|
+
// This is not targeted enough - it's trying to catch events like expand being set to breakout
|
|
123
|
+
var maybeWidthUpdated = tr.docChanged && oldState.doc.nodeSize === newState.doc.nodeSize && !nodeCountChanged;
|
|
124
|
+
var redrawDecorations = decorations === _view.DecorationSet.empty || (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== undefined && (meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== editorHeight || maybeWidthUpdated || nodeCountChanged || resizerMeta === false || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
|
|
125
|
+
|
|
107
126
|
// Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
|
|
108
|
-
|
|
109
|
-
if (redrawDecorations && isResizerResizing === false && api) {
|
|
127
|
+
if (redrawDecorations && !isResizerResizing && api) {
|
|
110
128
|
decorations = _view.DecorationSet.create(newState.doc, []);
|
|
111
129
|
var nodeDecs = (0, _decorations.nodeDecorations)(newState);
|
|
112
130
|
var mouseWrapperDecs = (0, _decorations.mouseMoveWrapperDecorations)(newState, api);
|
|
113
131
|
decorations = decorations.add(newState.doc, [].concat((0, _toConsumableArray2.default)(nodeDecs), (0, _toConsumableArray2.default)(mouseWrapperDecs)));
|
|
114
|
-
|
|
132
|
+
|
|
133
|
+
// Note: Quite often the handle is not in the right position after a node is moved
|
|
134
|
+
// it is safer for now to not show it when a node is moved
|
|
135
|
+
if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved)) {
|
|
115
136
|
var draghandleDec = (0, _decorations.dragHandleDecoration)(activeNode.pos, activeNode.anchorName, activeNode.nodeType, api);
|
|
116
137
|
decorations = decorations.add(newState.doc, [draghandleDec]);
|
|
117
138
|
}
|
|
@@ -119,8 +140,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
119
140
|
|
|
120
141
|
// Remove previous drag handle widget and draw new drag handle widget when activeNode changes
|
|
121
142
|
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) {
|
|
122
|
-
var _oldHandle = decorations.find().filter(function (
|
|
123
|
-
var spec =
|
|
143
|
+
var _oldHandle = decorations.find().filter(function (_ref7) {
|
|
144
|
+
var spec = _ref7.spec;
|
|
124
145
|
return spec.id === 'drag-handle';
|
|
125
146
|
});
|
|
126
147
|
decorations = decorations.remove(_oldHandle);
|
|
@@ -139,8 +160,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
139
160
|
|
|
140
161
|
// Remove drop target decoration when dragging stops
|
|
141
162
|
if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false && !tr.docChanged) {
|
|
142
|
-
var dropTargetDecs = decorations.find().filter(function (
|
|
143
|
-
var spec =
|
|
163
|
+
var dropTargetDecs = decorations.find().filter(function (_ref8) {
|
|
164
|
+
var spec = _ref8.spec;
|
|
144
165
|
return spec.type === 'drop-target-decoration';
|
|
145
166
|
});
|
|
146
167
|
decorations = decorations.remove(dropTargetDecs);
|
|
@@ -148,9 +169,9 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
148
169
|
|
|
149
170
|
// Map drop target decoration positions when the document changes
|
|
150
171
|
if (tr.docChanged && currentState.isDragging) {
|
|
151
|
-
decorationState = decorationState.map(function (
|
|
152
|
-
var index =
|
|
153
|
-
pos =
|
|
172
|
+
decorationState = decorationState.map(function (_ref9) {
|
|
173
|
+
var index = _ref9.index,
|
|
174
|
+
pos = _ref9.pos;
|
|
154
175
|
return {
|
|
155
176
|
index: index,
|
|
156
177
|
pos: tr.mapping.map(pos)
|
|
@@ -169,6 +190,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
169
190
|
anchorName: activeNode.anchorName,
|
|
170
191
|
nodeType: activeNode.nodeType
|
|
171
192
|
} : activeNode;
|
|
193
|
+
var isEmptyDoc = newState.doc.childCount === 1 && newState.doc.nodeSize <= 4;
|
|
172
194
|
return {
|
|
173
195
|
decorations: decorations,
|
|
174
196
|
decorationState: (_decorationState = decorationState) !== null && _decorationState !== void 0 ? _decorationState : currentState.decorationState,
|
|
@@ -176,7 +198,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
176
198
|
isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : currentState.isDragging,
|
|
177
199
|
isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
|
|
178
200
|
editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
|
|
179
|
-
isResizerResizing:
|
|
201
|
+
isResizerResizing: isResizerResizing,
|
|
180
202
|
isDocSizeLimitEnabled: initialState.isDocSizeLimitEnabled
|
|
181
203
|
};
|
|
182
204
|
}
|
|
@@ -209,10 +231,13 @@ var createPlugin = exports.createPlugin = function createPlugin(api) {
|
|
|
209
231
|
|
|
210
232
|
// Start observing the editor DOM element
|
|
211
233
|
resizeObserver.observe(dom);
|
|
234
|
+
|
|
235
|
+
// Start pragmatic monitors
|
|
236
|
+
var pragmaticCleanup = destroyFn(api);
|
|
212
237
|
return {
|
|
213
238
|
destroy: function destroy() {
|
|
214
239
|
resizeObserver.unobserve(dom);
|
|
215
|
-
|
|
240
|
+
pragmaticCleanup();
|
|
216
241
|
}
|
|
217
242
|
};
|
|
218
243
|
}
|
|
@@ -132,15 +132,6 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
|
|
|
132
132
|
}
|
|
133
133
|
api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.commands.setNodeDragged(start, anchorName, nodeType));
|
|
134
134
|
api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.focus();
|
|
135
|
-
},
|
|
136
|
-
onDrop: function onDrop() {
|
|
137
|
-
var _api$core7;
|
|
138
|
-
api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref6) {
|
|
139
|
-
var tr = _ref6.tr;
|
|
140
|
-
return tr.setMeta(_main.key, {
|
|
141
|
-
isDragging: false
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
135
|
}
|
|
145
136
|
});
|
|
146
137
|
}, [api, start, view, anchorName, nodeType]);
|
|
@@ -10,9 +10,7 @@ var _react = require("react");
|
|
|
10
10
|
var _react2 = require("@emotion/react");
|
|
11
11
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
12
12
|
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
13
|
-
var _element = require("@atlaskit/pragmatic-drag-and-drop-auto-scroll/element");
|
|
14
13
|
var _box = require("@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box");
|
|
15
|
-
var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
|
|
16
14
|
var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
|
|
17
15
|
/** @jsx jsx */
|
|
18
16
|
|
|
@@ -47,21 +45,11 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
|
|
|
47
45
|
if (!element) {
|
|
48
46
|
return;
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
var scrollable = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
52
|
-
if (scrollable) {
|
|
53
|
-
combined.push((0, _element.autoScrollForElements)({
|
|
54
|
-
element: scrollable
|
|
55
|
-
}));
|
|
56
|
-
}
|
|
57
|
-
combined.push((0, _adapter.dropTargetForElements)({
|
|
48
|
+
return (0, _adapter.dropTargetForElements)({
|
|
58
49
|
element: element,
|
|
59
50
|
getIsSticky: function getIsSticky() {
|
|
60
51
|
return true;
|
|
61
52
|
},
|
|
62
|
-
onDrag: function onDrag() {
|
|
63
|
-
scrollable.style.setProperty('scroll-behavior', 'unset');
|
|
64
|
-
},
|
|
65
53
|
onDragEnter: function onDragEnter() {
|
|
66
54
|
setIsDraggedOver(true);
|
|
67
55
|
},
|
|
@@ -70,7 +58,6 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
|
|
|
70
58
|
},
|
|
71
59
|
onDrop: function onDrop() {
|
|
72
60
|
var _api$blockControls;
|
|
73
|
-
scrollable.style.setProperty('scroll-behavior', null);
|
|
74
61
|
var _ref2 = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
|
|
75
62
|
activeNode = _ref2.activeNode,
|
|
76
63
|
decorationState = _ref2.decorationState;
|
|
@@ -103,8 +90,7 @@ var DropTarget = exports.DropTarget = function DropTarget(_ref) {
|
|
|
103
90
|
});
|
|
104
91
|
}
|
|
105
92
|
}
|
|
106
|
-
})
|
|
107
|
-
return _combine.combine.apply(void 0, combined);
|
|
93
|
+
});
|
|
108
94
|
}, [index, api]);
|
|
109
95
|
return (
|
|
110
96
|
// Note: Firefox has trouble with using a button element as the handle for drag and drop
|
|
@@ -9,7 +9,6 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
9
9
|
var _react = require("react");
|
|
10
10
|
var _react2 = require("@emotion/react");
|
|
11
11
|
var _bindEventListener = require("bind-event-listener");
|
|
12
|
-
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
13
12
|
var _dragHandlePositions = require("../utils/drag-handle-positions");
|
|
14
13
|
/** @jsx jsx */
|
|
15
14
|
|
|
@@ -29,21 +28,17 @@ var MouseMoveWrapper = exports.MouseMoveWrapper = function MouseMoveWrapper(_ref
|
|
|
29
28
|
anchorName = _ref.anchorName,
|
|
30
29
|
nodeType = _ref.nodeType,
|
|
31
30
|
getPos = _ref.getPos;
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// Using a ref for isDragging reduce re-renders
|
|
32
|
+
var isDragging = (0, _react.useRef)(false);
|
|
34
33
|
var _useState = (0, _react.useState)(false),
|
|
35
34
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
var _useState3 = (0, _react.useState)(false),
|
|
39
|
-
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
40
|
-
hideWrapper = _useState4[0],
|
|
41
|
-
setHideWrapper = _useState4[1];
|
|
35
|
+
hideWrapper = _useState2[0],
|
|
36
|
+
setHideWrapper = _useState2[1];
|
|
42
37
|
var ref = (0, _react.useRef)(null);
|
|
43
|
-
var
|
|
44
|
-
|
|
45
|
-
pos =
|
|
46
|
-
setPos =
|
|
38
|
+
var _useState3 = (0, _react.useState)(),
|
|
39
|
+
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
40
|
+
pos = _useState4[0],
|
|
41
|
+
setPos = _useState4[1];
|
|
47
42
|
(0, _react.useEffect)(function () {
|
|
48
43
|
// Adding this event listener to fix issue where wrapper isn't hidden if user navigates to node before page finishes loading
|
|
49
44
|
// This will be removed when we refactor to remove this component
|
|
@@ -63,34 +58,42 @@ var MouseMoveWrapper = exports.MouseMoveWrapper = function MouseMoveWrapper(_ref
|
|
|
63
58
|
};
|
|
64
59
|
}, []);
|
|
65
60
|
var onMouseEnter = (0, _react.useCallback)(function () {
|
|
66
|
-
if (!isDragging) {
|
|
61
|
+
if (!isDragging.current) {
|
|
67
62
|
setHideWrapper(true);
|
|
68
63
|
}
|
|
69
64
|
var pos = getPos();
|
|
70
65
|
if (pos === undefined) {
|
|
71
66
|
return;
|
|
72
67
|
}
|
|
73
|
-
if (api && api.blockControls && !isDragging) {
|
|
68
|
+
if (api && api.blockControls && !isDragging.current) {
|
|
74
69
|
var _api$core;
|
|
75
70
|
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api.blockControls.commands.showDragHandleAt(pos, anchorName, nodeType));
|
|
76
71
|
}
|
|
77
|
-
}, [
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
var
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
if ((blockControlsState === null || blockControlsState === void 0 || (_blockControlsState$a = blockControlsState.activeNode) === null || _blockControlsState$a === void 0 ? void 0 : _blockControlsState$a.pos) !== pos && !(blockControlsState !== null && blockControlsState !== void 0 && blockControlsState.isDragging)) {
|
|
72
|
+
}, [getPos, isDragging, api, anchorName, nodeType]);
|
|
73
|
+
|
|
74
|
+
//THIS IS TRIGGERED A LOT!
|
|
75
|
+
var onSharedStateChange = (0, _react.useCallback)(function (_ref2) {
|
|
76
|
+
var _nextSharedState$acti;
|
|
77
|
+
var nextSharedState = _ref2.nextSharedState;
|
|
78
|
+
if ((nextSharedState === null || nextSharedState === void 0 || (_nextSharedState$acti = nextSharedState.activeNode) === null || _nextSharedState$acti === void 0 ? void 0 : _nextSharedState$acti.anchorName) !== anchorName && !isDragging.current) {
|
|
86
79
|
setHideWrapper(false);
|
|
87
|
-
return;
|
|
88
80
|
}
|
|
89
|
-
if (
|
|
81
|
+
if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.isDragging && !isDragging.current) {
|
|
82
|
+
isDragging.current = true;
|
|
90
83
|
setHideWrapper(true);
|
|
91
|
-
return;
|
|
92
84
|
}
|
|
93
|
-
|
|
85
|
+
if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isDragging) === false && isDragging.current) {
|
|
86
|
+
isDragging.current = false;
|
|
87
|
+
setHideWrapper(false);
|
|
88
|
+
}
|
|
89
|
+
}, [anchorName]);
|
|
90
|
+
(0, _react.useEffect)(function () {
|
|
91
|
+
var _api$blockControls;
|
|
92
|
+
var unbind = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.onChange(onSharedStateChange);
|
|
93
|
+
return function () {
|
|
94
|
+
unbind === null || unbind === void 0 || unbind();
|
|
95
|
+
};
|
|
96
|
+
}, [onSharedStateChange, api]);
|
|
94
97
|
(0, _react.useLayoutEffect)(function () {
|
|
95
98
|
var supportsAnchor = CSS.supports('height', "anchor-size(".concat(anchorName, " height)")) && CSS.supports('top', "anchor(".concat(anchorName, " start)"));
|
|
96
99
|
if (supportsAnchor) {
|
|
@@ -6,6 +6,7 @@ import { DropTarget } from '../ui/drop-target';
|
|
|
6
6
|
import { MouseMoveWrapper } from '../ui/mouse-move-wrapper';
|
|
7
7
|
export const dropTargetDecorations = (oldState, newState, api) => {
|
|
8
8
|
const decs = [];
|
|
9
|
+
unmountDecorations('data-blocks-drop-target-container');
|
|
9
10
|
// Decoration state is used to keep track of the position of the drop targets
|
|
10
11
|
// and allows us to easily map the updated position in the plugin apply method.
|
|
11
12
|
const decorationState = [];
|
|
@@ -16,6 +17,7 @@ export const dropTargetDecorations = (oldState, newState, api) => {
|
|
|
16
17
|
});
|
|
17
18
|
decs.push(Decoration.widget(pos, () => {
|
|
18
19
|
const element = document.createElement('div');
|
|
20
|
+
element.setAttribute('data-blocks-drop-target-container', 'true');
|
|
19
21
|
ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
|
|
20
22
|
api,
|
|
21
23
|
index
|
|
@@ -40,6 +42,7 @@ export const dropTargetDecorations = (oldState, newState, api) => {
|
|
|
40
42
|
});
|
|
41
43
|
decs.push(Decoration.widget(newState.doc.nodeSize - 2, () => {
|
|
42
44
|
const element = document.createElement('div');
|
|
45
|
+
element.setAttribute('data-blocks-drop-target-container', 'true');
|
|
43
46
|
ReactDOM.render( /*#__PURE__*/createElement(DropTarget, {
|
|
44
47
|
api,
|
|
45
48
|
index: decorationState.length
|
|
@@ -73,10 +76,12 @@ export const nodeDecorations = newState => {
|
|
|
73
76
|
*/
|
|
74
77
|
export const mouseMoveWrapperDecorations = (newState, api) => {
|
|
75
78
|
const decs = [];
|
|
79
|
+
unmountDecorations('data-blocks-decoration-container');
|
|
76
80
|
newState.doc.descendants((node, pos, _parent, index) => {
|
|
77
81
|
const anchorName = `--node-anchor-${node.type.name}-${index}`;
|
|
78
82
|
decs.push(Decoration.widget(pos, (view, getPos) => {
|
|
79
83
|
const element = document.createElement('div');
|
|
84
|
+
element.setAttribute('data-blocks-decoration-container', 'true');
|
|
80
85
|
ReactDOM.render( /*#__PURE__*/createElement(MouseMoveWrapper, {
|
|
81
86
|
view,
|
|
82
87
|
api,
|
|
@@ -101,6 +106,7 @@ export const dragHandleDecoration = (pos, anchorName, nodeType, api) => {
|
|
|
101
106
|
return Decoration.widget(pos, (view, getPos) => {
|
|
102
107
|
const element = document.createElement('div');
|
|
103
108
|
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
109
|
+
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
104
110
|
ReactDOM.render( /*#__PURE__*/createElement(DragHandle, {
|
|
105
111
|
view,
|
|
106
112
|
api,
|
|
@@ -111,6 +117,17 @@ export const dragHandleDecoration = (pos, anchorName, nodeType, api) => {
|
|
|
111
117
|
return element;
|
|
112
118
|
}, {
|
|
113
119
|
side: -1,
|
|
114
|
-
id: 'drag-handle'
|
|
120
|
+
id: 'drag-handle',
|
|
121
|
+
destroy: node => {
|
|
122
|
+
ReactDOM.unmountComponentAtNode(node);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
const unmountDecorations = selector => {
|
|
127
|
+
// Removing decorations manually instead of using native destroy function in prosemirror API
|
|
128
|
+
// as it was more responsive and causes less re-rendering
|
|
129
|
+
const decorationsToRemove = document.querySelectorAll(`[${selector}="true"]`);
|
|
130
|
+
decorationsToRemove.forEach(el => {
|
|
131
|
+
ReactDOM.unmountComponentAtNode(el);
|
|
115
132
|
});
|
|
116
133
|
};
|
|
@@ -4,25 +4,46 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
|
4
4
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
5
5
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
6
6
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
7
|
+
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
|
|
8
|
+
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
7
9
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
8
10
|
import { dragHandleDecoration, dropTargetDecorations, mouseMoveWrapperDecorations, nodeDecorations } from './decorations';
|
|
9
11
|
export const key = new PluginKey('blockControls');
|
|
10
12
|
const destroyFn = api => {
|
|
11
|
-
|
|
13
|
+
const scrollable = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
14
|
+
const cleanupFn = [];
|
|
15
|
+
if (scrollable) {
|
|
16
|
+
cleanupFn.push(autoScrollForElements({
|
|
17
|
+
element: scrollable
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
cleanupFn.push(monitorForElements({
|
|
12
21
|
canMonitor: ({
|
|
13
22
|
source
|
|
14
23
|
}) => source.data.type === 'element',
|
|
24
|
+
onDragStart: () => {
|
|
25
|
+
scrollable.style.setProperty('scroll-behavior', 'unset');
|
|
26
|
+
},
|
|
15
27
|
onDrop: ({
|
|
16
28
|
location,
|
|
17
29
|
source
|
|
18
30
|
}) => {
|
|
31
|
+
var _api$core;
|
|
32
|
+
scrollable.style.setProperty('scroll-behavior', null);
|
|
33
|
+
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
34
|
+
tr
|
|
35
|
+
}) => {
|
|
36
|
+
return tr.setMeta(key, {
|
|
37
|
+
isDragging: false
|
|
38
|
+
});
|
|
39
|
+
});
|
|
19
40
|
// if no drop targets are rendered, assume that drop is invalid
|
|
20
41
|
if (location.current.dropTargets.length === 0) {
|
|
21
|
-
var _api$
|
|
42
|
+
var _api$core2;
|
|
22
43
|
const {
|
|
23
44
|
start
|
|
24
45
|
} = source.data;
|
|
25
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
46
|
+
api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(({
|
|
26
47
|
tr
|
|
27
48
|
}) => {
|
|
28
49
|
var _api$analytics;
|
|
@@ -42,7 +63,8 @@ const destroyFn = api => {
|
|
|
42
63
|
});
|
|
43
64
|
}
|
|
44
65
|
}
|
|
45
|
-
});
|
|
66
|
+
}));
|
|
67
|
+
return combine(...cleanupFn);
|
|
46
68
|
};
|
|
47
69
|
const initialState = {
|
|
48
70
|
decorations: DecorationSet.empty,
|
|
@@ -50,8 +72,6 @@ const initialState = {
|
|
|
50
72
|
activeNode: null,
|
|
51
73
|
isDragging: false,
|
|
52
74
|
isMenuOpen: false,
|
|
53
|
-
start: null,
|
|
54
|
-
end: null,
|
|
55
75
|
editorHeight: 0,
|
|
56
76
|
isResizerResizing: false,
|
|
57
77
|
isDocSizeLimitEnabled: false
|
|
@@ -68,7 +88,7 @@ export const createPlugin = api => {
|
|
|
68
88
|
return initialState;
|
|
69
89
|
},
|
|
70
90
|
apply(tr, currentState, oldState, newState) {
|
|
71
|
-
var _decorationState, _meta$activeNode, _meta$isDragging, _meta$editorHeight
|
|
91
|
+
var _decorationState, _meta$activeNode, _meta$isDragging, _meta$editorHeight;
|
|
72
92
|
if (initialState.isDocSizeLimitEnabled && newState.doc.nodeSize > DRAG_AND_DROP_DOC_SIZE_LIMIT) {
|
|
73
93
|
return initialState;
|
|
74
94
|
}
|
|
@@ -85,28 +105,30 @@ export const createPlugin = api => {
|
|
|
85
105
|
// If tables or media are being resized, we want to hide the drag handle
|
|
86
106
|
const resizerMeta = tr.getMeta('is-resizer-resizing');
|
|
87
107
|
isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
|
|
88
|
-
const isEmptyDoc = newState.doc.childCount === 1 && newState.doc.nodeSize <= 4;
|
|
89
|
-
|
|
90
|
-
// This is not targeted enough - it's trying to catch events like expand being set to breakout
|
|
91
|
-
const maybeWidthUpdated = tr.docChanged && oldState.doc.nodeSize === newState.doc.nodeSize && oldState.doc.childCount === newState.doc.childCount;
|
|
92
108
|
const nodeCountChanged = oldState.doc.childCount !== newState.doc.childCount;
|
|
93
109
|
|
|
94
110
|
// During resize, remove the drag handle widget
|
|
95
|
-
if (isResizerResizing || nodeCountChanged) {
|
|
111
|
+
if (isResizerResizing || nodeCountChanged || meta !== null && meta !== void 0 && meta.nodeMoved) {
|
|
96
112
|
const oldHandle = decorations.find().filter(({
|
|
97
113
|
spec
|
|
98
114
|
}) => spec.id === 'drag-handle');
|
|
99
115
|
decorations = decorations.remove(oldHandle);
|
|
100
116
|
}
|
|
101
117
|
|
|
118
|
+
// This is not targeted enough - it's trying to catch events like expand being set to breakout
|
|
119
|
+
const maybeWidthUpdated = tr.docChanged && oldState.doc.nodeSize === newState.doc.nodeSize && !nodeCountChanged;
|
|
120
|
+
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 || resizerMeta === false || !!(meta !== null && meta !== void 0 && meta.nodeMoved) && tr.docChanged;
|
|
121
|
+
|
|
102
122
|
// Draw node and mouseWrapper decorations at top level node if decorations is empty, editor height changes or node is moved
|
|
103
|
-
|
|
104
|
-
if (redrawDecorations && isResizerResizing === false && api) {
|
|
123
|
+
if (redrawDecorations && !isResizerResizing && api) {
|
|
105
124
|
decorations = DecorationSet.create(newState.doc, []);
|
|
106
125
|
const nodeDecs = nodeDecorations(newState);
|
|
107
126
|
const mouseWrapperDecs = mouseMoveWrapperDecorations(newState, api);
|
|
108
127
|
decorations = decorations.add(newState.doc, [...nodeDecs, ...mouseWrapperDecs]);
|
|
109
|
-
|
|
128
|
+
|
|
129
|
+
// Note: Quite often the handle is not in the right position after a node is moved
|
|
130
|
+
// it is safer for now to not show it when a node is moved
|
|
131
|
+
if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved)) {
|
|
110
132
|
const draghandleDec = dragHandleDecoration(activeNode.pos, activeNode.anchorName, activeNode.nodeType, api);
|
|
111
133
|
decorations = decorations.add(newState.doc, [draghandleDec]);
|
|
112
134
|
}
|
|
@@ -164,6 +186,7 @@ export const createPlugin = api => {
|
|
|
164
186
|
anchorName: activeNode.anchorName,
|
|
165
187
|
nodeType: activeNode.nodeType
|
|
166
188
|
} : activeNode;
|
|
189
|
+
const isEmptyDoc = newState.doc.childCount === 1 && newState.doc.nodeSize <= 4;
|
|
167
190
|
return {
|
|
168
191
|
decorations,
|
|
169
192
|
decorationState: (_decorationState = decorationState) !== null && _decorationState !== void 0 ? _decorationState : currentState.decorationState,
|
|
@@ -171,7 +194,7 @@ export const createPlugin = api => {
|
|
|
171
194
|
isDragging: (_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : currentState.isDragging,
|
|
172
195
|
isMenuOpen: meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen,
|
|
173
196
|
editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : currentState.editorHeight,
|
|
174
|
-
isResizerResizing:
|
|
197
|
+
isResizerResizing: isResizerResizing,
|
|
175
198
|
isDocSizeLimitEnabled: initialState.isDocSizeLimitEnabled
|
|
176
199
|
};
|
|
177
200
|
}
|
|
@@ -204,10 +227,13 @@ export const createPlugin = api => {
|
|
|
204
227
|
|
|
205
228
|
// Start observing the editor DOM element
|
|
206
229
|
resizeObserver.observe(dom);
|
|
230
|
+
|
|
231
|
+
// Start pragmatic monitors
|
|
232
|
+
const pragmaticCleanup = destroyFn(api);
|
|
207
233
|
return {
|
|
208
234
|
destroy() {
|
|
209
235
|
resizeObserver.unobserve(dom);
|
|
210
|
-
|
|
236
|
+
pragmaticCleanup();
|
|
211
237
|
}
|
|
212
238
|
};
|
|
213
239
|
}
|