@atlaskit/editor-plugin-block-controls 8.0.10 → 8.0.11
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 +10 -0
- package/dist/cjs/editor-commands/move-node-with-block-menu.js +6 -6
- package/dist/cjs/editor-commands/move-node.js +0 -3
- package/dist/cjs/editor-commands/utils/move-node-utils.js +57 -45
- package/dist/cjs/pm-plugins/handle-mouse-over.js +5 -0
- package/dist/cjs/pm-plugins/selection-preservation/pm-plugin.js +50 -28
- package/dist/cjs/pm-plugins/selection-preservation/utils.js +1 -13
- package/dist/es2019/editor-commands/move-node-with-block-menu.js +7 -7
- package/dist/es2019/editor-commands/move-node.js +0 -3
- package/dist/es2019/editor-commands/utils/move-node-utils.js +49 -37
- package/dist/es2019/pm-plugins/handle-mouse-over.js +5 -0
- package/dist/es2019/pm-plugins/selection-preservation/pm-plugin.js +52 -30
- package/dist/es2019/pm-plugins/selection-preservation/utils.js +0 -13
- package/dist/esm/editor-commands/move-node-with-block-menu.js +7 -7
- package/dist/esm/editor-commands/move-node.js +0 -3
- package/dist/esm/editor-commands/utils/move-node-utils.js +57 -44
- package/dist/esm/pm-plugins/handle-mouse-over.js +5 -0
- package/dist/esm/pm-plugins/selection-preservation/pm-plugin.js +51 -29
- package/dist/esm/pm-plugins/selection-preservation/utils.js +0 -12
- package/dist/types/editor-commands/utils/move-node-utils.d.ts +16 -8
- package/dist/types/pm-plugins/selection-preservation/utils.d.ts +0 -7
- package/dist/types-ts4.5/editor-commands/utils/move-node-utils.d.ts +16 -8
- package/dist/types-ts4.5/pm-plugins/selection-preservation/utils.d.ts +0 -7
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-controls
|
|
2
2
|
|
|
3
|
+
## 8.0.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`de045021d126d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/de045021d126d) -
|
|
8
|
+
EDITOR-4435 fix code block selection focus
|
|
9
|
+
- [`76afb688dff6a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/76afb688dff6a) -
|
|
10
|
+
[ux] Update move function to leverage preserveSelection logic for different types of selection
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
3
13
|
## 8.0.10
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -36,12 +36,12 @@ var moveNodeWithBlockMenu = exports.moveNodeWithBlockMenu = function moveNodeWit
|
|
|
36
36
|
var preservedSelection = api === null || api === void 0 || (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
|
|
37
37
|
var selection = preservedSelection !== null && preservedSelection !== void 0 ? preservedSelection : tr.selection;
|
|
38
38
|
|
|
39
|
-
//
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
// Use getNodeBoundsFromSelection to get the proper block boundaries
|
|
40
|
+
var nodeBounds = (0, _moveNodeUtils.getNodeBoundsFromSelection)(selection);
|
|
41
|
+
if (!nodeBounds) {
|
|
42
|
+
return tr;
|
|
43
|
+
}
|
|
44
|
+
var currentNodePos = nodeBounds.from;
|
|
45
45
|
var $from = selection.$from,
|
|
46
46
|
$to = selection.$to;
|
|
47
47
|
var depth = tr.doc.resolve(currentNodePos).depth;
|
|
@@ -394,9 +394,6 @@ var moveNode = exports.moveNode = function moveNode(api) {
|
|
|
394
394
|
if (!convertedNode) {
|
|
395
395
|
return tr;
|
|
396
396
|
}
|
|
397
|
-
if ((sourceNode === null || sourceNode === void 0 ? void 0 : sourceNode.type.name) === 'taskList' && sliceFrom > 0 && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
|
|
398
|
-
sliceFrom = sliceFrom - 1;
|
|
399
|
-
}
|
|
400
397
|
|
|
401
398
|
// Currently we don't support breakout mark for children nodes of bodiedSyncBlock node
|
|
402
399
|
// Hence strip out the mark for now
|
|
@@ -3,42 +3,57 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getShouldMoveNode = exports.getPosWhenMoveNodeUp = exports.getPosWhenMoveNodeDown = exports.
|
|
7
|
-
var _selection = require("@atlaskit/editor-common/selection");
|
|
6
|
+
exports.getShouldMoveNode = exports.getPosWhenMoveNodeUp = exports.getPosWhenMoveNodeDown = exports.getNodeBoundsFromSelection = exports.canMoveNodeUpOrDown = void 0;
|
|
8
7
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
9
8
|
var _utils = require("@atlaskit/editor-tables/utils");
|
|
10
9
|
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
var _selection = require("../../pm-plugins/utils/selection");
|
|
11
|
+
/**
|
|
12
|
+
* Gets the current node position and bounds from the selection using the preserved selection logic.
|
|
13
|
+
* This ensures consistency with how the block controls plugin handles selection boundaries.
|
|
14
|
+
*
|
|
15
|
+
* Special handling for tables: When moving a table as a block, we need the outer table node's
|
|
16
|
+
* position, not the internal cell selection that createPreservedSelection returns.
|
|
17
|
+
*
|
|
18
|
+
* @param selection The current editor selection
|
|
19
|
+
* @returns An object with from and to positions, or undefined if selection is invalid
|
|
20
|
+
*/
|
|
21
|
+
var getNodeBoundsFromSelection = exports.getNodeBoundsFromSelection = function getNodeBoundsFromSelection(selection) {
|
|
22
|
+
// Special case: if a table is selected, we want to move the entire table node
|
|
23
|
+
var tableInfo = (0, _utils.findTable)(selection);
|
|
24
|
+
if (tableInfo && (0, _utils.isTableSelected)(selection)) {
|
|
25
|
+
var tablePos = tableInfo.pos;
|
|
26
|
+
var tableTo = tablePos + tableInfo.node.nodeSize;
|
|
27
|
+
return {
|
|
28
|
+
from: tablePos,
|
|
29
|
+
to: tableTo
|
|
30
|
+
};
|
|
19
31
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (selection.$from.depth > 0) {
|
|
34
|
-
currentNodePos = (0, _getNestedNodePosition.getNestedNodePosition)({
|
|
35
|
-
selection: selection,
|
|
36
|
-
schema: schema,
|
|
37
|
-
resolve: resolve
|
|
38
|
-
});
|
|
32
|
+
|
|
33
|
+
// Special case: if a media node (file) is selected, we need to get the parent mediaGroup
|
|
34
|
+
// This handles the case where clicking on a file creates a NodeSelection of the media node
|
|
35
|
+
// but we want to move the entire mediaGroup that wraps it
|
|
36
|
+
if (selection instanceof _state.NodeSelection && selection.node.type.name === 'media' && selection.node.attrs.type === 'file' && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
|
|
37
|
+
// The media node is wrapped in a mediaGroup, so we need to get the parent position
|
|
38
|
+
var mediaGroupPos = selection.$from.pos - 1;
|
|
39
|
+
var mediaGroupNode = selection.$from.doc.nodeAt(mediaGroupPos);
|
|
40
|
+
if (mediaGroupNode && mediaGroupNode.type.name === 'mediaGroup') {
|
|
41
|
+
return {
|
|
42
|
+
from: mediaGroupPos,
|
|
43
|
+
to: mediaGroupPos + mediaGroupNode.nodeSize
|
|
44
|
+
};
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
|
-
|
|
47
|
+
|
|
48
|
+
// Use createPreservedSelection to get properly expanded block boundaries
|
|
49
|
+
var preservedSelection = (0, _selection.createPreservedSelection)(selection.$from, selection.$to);
|
|
50
|
+
if (!preservedSelection) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
from: preservedSelection.from,
|
|
55
|
+
to: preservedSelection.to
|
|
56
|
+
};
|
|
42
57
|
};
|
|
43
58
|
var getPosWhenMoveNodeUp = exports.getPosWhenMoveNodeUp = function getPosWhenMoveNodeUp($currentNodePos, currentNodePos) {
|
|
44
59
|
var nodeIndex = $currentNodePos.index();
|
|
@@ -48,10 +63,10 @@ var getPosWhenMoveNodeUp = exports.getPosWhenMoveNodeUp = function getPosWhenMov
|
|
|
48
63
|
}
|
|
49
64
|
return nodeBefore ? currentNodePos - nodeBefore.nodeSize : -1;
|
|
50
65
|
};
|
|
51
|
-
var getPosWhenMoveNodeDown = exports.getPosWhenMoveNodeDown = function getPosWhenMoveNodeDown(
|
|
52
|
-
var $currentNodePos =
|
|
53
|
-
nodeAfterPos =
|
|
54
|
-
tr =
|
|
66
|
+
var getPosWhenMoveNodeDown = exports.getPosWhenMoveNodeDown = function getPosWhenMoveNodeDown(_ref) {
|
|
67
|
+
var $currentNodePos = _ref.$currentNodePos,
|
|
68
|
+
nodeAfterPos = _ref.nodeAfterPos,
|
|
69
|
+
tr = _ref.tr;
|
|
55
70
|
var endOfDoc = $currentNodePos.end();
|
|
56
71
|
if (nodeAfterPos > endOfDoc) {
|
|
57
72
|
return -1;
|
|
@@ -68,27 +83,24 @@ var getPosWhenMoveNodeDown = exports.getPosWhenMoveNodeDown = function getPosWhe
|
|
|
68
83
|
// if not the last node, move to the end of the next node
|
|
69
84
|
return nodeAfter ? nodeAfterPos + nodeAfter.nodeSize : -1;
|
|
70
85
|
};
|
|
71
|
-
var getShouldMoveNode = exports.getShouldMoveNode = function getShouldMoveNode(
|
|
72
|
-
var currentNodePos =
|
|
73
|
-
moveToPos =
|
|
74
|
-
tr =
|
|
86
|
+
var getShouldMoveNode = exports.getShouldMoveNode = function getShouldMoveNode(_ref2) {
|
|
87
|
+
var currentNodePos = _ref2.currentNodePos,
|
|
88
|
+
moveToPos = _ref2.moveToPos,
|
|
89
|
+
tr = _ref2.tr;
|
|
75
90
|
// only move the node if the destination is at the same depth, not support moving a nested node to a parent node
|
|
76
91
|
return moveToPos > -1 && tr.doc.resolve(currentNodePos).depth === tr.doc.resolve(moveToPos).depth;
|
|
77
92
|
};
|
|
78
93
|
var canMoveNodeUpOrDown = exports.canMoveNodeUpOrDown = function canMoveNodeUpOrDown(tr) {
|
|
79
|
-
var
|
|
80
|
-
|
|
81
|
-
schema: tr.doc.type.schema,
|
|
82
|
-
resolve: tr.doc.resolve.bind(tr.doc)
|
|
83
|
-
});
|
|
84
|
-
if (currentNodePos <= -1) {
|
|
94
|
+
var nodeBounds = getNodeBoundsFromSelection(tr.selection);
|
|
95
|
+
if (!nodeBounds || nodeBounds.from <= -1) {
|
|
85
96
|
return {
|
|
86
97
|
moveUp: false,
|
|
87
98
|
moveDown: false
|
|
88
99
|
};
|
|
89
100
|
}
|
|
101
|
+
var currentNodePos = nodeBounds.from;
|
|
90
102
|
var $currentNodePos = tr.doc.resolve(currentNodePos);
|
|
91
|
-
var nodeAfterPos =
|
|
103
|
+
var nodeAfterPos = nodeBounds.to;
|
|
92
104
|
var moveUpPos = getPosWhenMoveNodeUp($currentNodePos, currentNodePos);
|
|
93
105
|
var moveDownPos = getPosWhenMoveNodeDown({
|
|
94
106
|
$currentNodePos: $currentNodePos,
|
|
@@ -64,6 +64,11 @@ var handleMouseOver = exports.handleMouseOver = function handleMouseOver(view, e
|
|
|
64
64
|
return false;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
// If the editor view is not in focus when the block menu is open, do not update the drag handle
|
|
68
|
+
if (!view.hasFocus() && isMenuOpen && (0, _expValEquals.expValEquals)('platform_editor_block_menu', 'isEnabled', true)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
67
72
|
// Most mouseover events don't fire during drag but some can slip through
|
|
68
73
|
// when the drag begins. This prevents those.
|
|
69
74
|
if (isDragging) {
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.createSelectionPreservationPlugin = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _bindEventListener = require("bind-event-listener");
|
|
9
10
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
10
11
|
var _styles = require("@atlaskit/editor-common/styles");
|
|
11
12
|
var _main = require("../main");
|
|
@@ -66,7 +67,7 @@ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugi
|
|
|
66
67
|
newState.preservedSelection = (0, _selection.mapPreservedSelection)(newState.preservedSelection, tr);
|
|
67
68
|
}
|
|
68
69
|
if (!(0, _utils.compareSelections)(newState.preservedSelection, pluginState.preservedSelection)) {
|
|
69
|
-
if (newState
|
|
70
|
+
if (newState.preservedSelection) {
|
|
70
71
|
var _api$selection;
|
|
71
72
|
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.commands) === null || _api$selection === void 0 ? void 0 : _api$selection.setBlockSelection(newState.preservedSelection));
|
|
72
73
|
} else {
|
|
@@ -85,8 +86,8 @@ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugi
|
|
|
85
86
|
return null;
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
// Auto-stop if user explicitly changes selection
|
|
89
|
-
if ((0, _utils.hasUserSelectionChange)(transactions)
|
|
89
|
+
// Auto-stop if user explicitly changes selection
|
|
90
|
+
if ((0, _utils.hasUserSelectionChange)(transactions)) {
|
|
90
91
|
return (0, _editorCommands.stopPreservingSelection)({
|
|
91
92
|
tr: newState.tr
|
|
92
93
|
});
|
|
@@ -106,10 +107,51 @@ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugi
|
|
|
106
107
|
}
|
|
107
108
|
return newState.tr.setSelection(newSelection);
|
|
108
109
|
},
|
|
109
|
-
view: function view() {
|
|
110
|
+
view: function view(initialView) {
|
|
111
|
+
var view = initialView;
|
|
112
|
+
var unbindDocumentMouseDown = (0, _bindEventListener.bind)(document, {
|
|
113
|
+
type: 'mousedown',
|
|
114
|
+
listener: function listener(e) {
|
|
115
|
+
if (!(e.target instanceof HTMLElement)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
var _ref = _pluginKey.selectionPreservationPluginKey.getState(view.state) || {},
|
|
119
|
+
preservedSelection = _ref.preservedSelection;
|
|
120
|
+
|
|
121
|
+
// If there is no current preserved selection or the editor is not focused, do nothing
|
|
122
|
+
if (!preservedSelection) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
var clickedDragHandle = !!e.target.closest(_styles.DRAG_HANDLE_SELECTOR);
|
|
126
|
+
|
|
127
|
+
// When mouse down on a drag handle we continue preserving the selection
|
|
128
|
+
if (clickedDragHandle) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
var clickedOutsideEditor = !e.target.closest('.ProseMirror');
|
|
132
|
+
|
|
133
|
+
// When mouse down outside the editor continue to preserve the selection
|
|
134
|
+
if (clickedOutsideEditor) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Otherwise mouse down anywhere else in the editor stops preserving the selection
|
|
139
|
+
var tr = view.state.tr;
|
|
140
|
+
(0, _editorCommands.stopPreservingSelection)({
|
|
141
|
+
tr: tr
|
|
142
|
+
});
|
|
143
|
+
view.dispatch(tr);
|
|
144
|
+
},
|
|
145
|
+
// Use capture phase to stop preservation before appendTransaction runs,
|
|
146
|
+
// preventing unwanted selection restoration when the user clicks into the editor.
|
|
147
|
+
options: {
|
|
148
|
+
capture: true
|
|
149
|
+
}
|
|
150
|
+
});
|
|
110
151
|
return {
|
|
111
|
-
update: function update(
|
|
152
|
+
update: function update(updateView, prevState) {
|
|
112
153
|
var _selectionPreservatio, _selectionPreservatio2, _key$getState, _key$getState2;
|
|
154
|
+
view = updateView;
|
|
113
155
|
var prevPreservedSelection = (_selectionPreservatio = _pluginKey.selectionPreservationPluginKey.getState(prevState)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection;
|
|
114
156
|
var currPreservedSelection = (_selectionPreservatio2 = _pluginKey.selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio2 === void 0 ? void 0 : _selectionPreservatio2.preservedSelection;
|
|
115
157
|
var prevActiveNode = (_key$getState = _main.key.getState(prevState)) === null || _key$getState === void 0 ? void 0 : _key$getState.activeNode;
|
|
@@ -117,33 +159,13 @@ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugi
|
|
|
117
159
|
if (currPreservedSelection && view.hasFocus() && (!(0, _utils.compareSelections)(prevPreservedSelection, currPreservedSelection) || prevActiveNode !== currActiveNode)) {
|
|
118
160
|
(0, _utils.syncDOMSelection)(view.state.selection);
|
|
119
161
|
}
|
|
162
|
+
},
|
|
163
|
+
destroy: function destroy() {
|
|
164
|
+
unbindDocumentMouseDown();
|
|
120
165
|
}
|
|
121
166
|
};
|
|
122
167
|
},
|
|
123
168
|
props: {
|
|
124
|
-
handleClick: function handleClick(view, pos, event) {
|
|
125
|
-
var _ref = _pluginKey.selectionPreservationPluginKey.getState(view.state) || {},
|
|
126
|
-
preservedSelection = _ref.preservedSelection;
|
|
127
|
-
|
|
128
|
-
// If there is no current preserved selection, do nothing
|
|
129
|
-
if (!preservedSelection) {
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
var clickedDragHandle = event.target instanceof HTMLElement && event.target.closest(_styles.DRAG_HANDLE_SELECTOR);
|
|
133
|
-
|
|
134
|
-
// When clicking a drag handle we continue preserving the selection
|
|
135
|
-
if (!clickedDragHandle) {
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Otherwise clicking anywhere else in the editor stops preserving the selection
|
|
140
|
-
var tr = view.state.tr;
|
|
141
|
-
(0, _editorCommands.stopPreservingSelection)({
|
|
142
|
-
tr: tr
|
|
143
|
-
});
|
|
144
|
-
view.dispatch(tr);
|
|
145
|
-
return false;
|
|
146
|
-
},
|
|
147
169
|
handleKeyDown: function handleKeyDown(view, event) {
|
|
148
170
|
var _api$core, _api$blockControls;
|
|
149
171
|
var _ref2 = _pluginKey.selectionPreservationPluginKey.getState(view.state) || {},
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.syncDOMSelection = exports.
|
|
6
|
+
exports.syncDOMSelection = exports.hasUserSelectionChange = exports.getSelectionPreservationMeta = exports.compareSelections = void 0;
|
|
7
7
|
var _pluginKey = require("./plugin-key");
|
|
8
8
|
/**
|
|
9
9
|
* Detects if any of the transactions include user-driven selection changes.
|
|
@@ -20,18 +20,6 @@ var getSelectionPreservationMeta = exports.getSelectionPreservationMeta = functi
|
|
|
20
20
|
return tr.getMeta(_pluginKey.selectionPreservationPluginKey);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
/**
|
|
24
|
-
* Checks if the current selection is within a code block.
|
|
25
|
-
*
|
|
26
|
-
* @param selection The current selection to check.
|
|
27
|
-
* @returns True if the selection is within a code block, otherwise false.
|
|
28
|
-
*/
|
|
29
|
-
var isSelectionWithinCodeBlock = exports.isSelectionWithinCodeBlock = function isSelectionWithinCodeBlock(_ref) {
|
|
30
|
-
var $from = _ref.$from,
|
|
31
|
-
$to = _ref.$to;
|
|
32
|
-
return $from.sameParent($to) && $from.parent.type.name === 'codeBlock';
|
|
33
|
-
};
|
|
34
|
-
|
|
35
23
|
/**
|
|
36
24
|
* Compares two selections for equality based on their from and to positions.
|
|
37
25
|
*
|
|
@@ -4,7 +4,7 @@ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equ
|
|
|
4
4
|
import { key } from '../pm-plugins/main';
|
|
5
5
|
import { mapPreservedSelection } from '../pm-plugins/utils/selection';
|
|
6
6
|
import { moveNode } from './move-node';
|
|
7
|
-
import { canMoveNodeUpOrDown,
|
|
7
|
+
import { canMoveNodeUpOrDown, getNodeBoundsFromSelection } from './utils/move-node-utils';
|
|
8
8
|
const getSelectionToIndex = (fromIndex, $to, depth) => {
|
|
9
9
|
const toIndex = $to.index(depth);
|
|
10
10
|
const toIndexAfter = $to.indexAfter(depth);
|
|
@@ -27,12 +27,12 @@ export const moveNodeWithBlockMenu = (api, direction) => {
|
|
|
27
27
|
const preservedSelection = api === null || api === void 0 ? void 0 : (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
|
|
28
28
|
const selection = preservedSelection !== null && preservedSelection !== void 0 ? preservedSelection : tr.selection;
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
// Use getNodeBoundsFromSelection to get the proper block boundaries
|
|
31
|
+
const nodeBounds = getNodeBoundsFromSelection(selection);
|
|
32
|
+
if (!nodeBounds) {
|
|
33
|
+
return tr;
|
|
34
|
+
}
|
|
35
|
+
const currentNodePos = nodeBounds.from;
|
|
36
36
|
const {
|
|
37
37
|
$from,
|
|
38
38
|
$to
|
|
@@ -396,9 +396,6 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
|
|
|
396
396
|
if (!convertedNode) {
|
|
397
397
|
return tr;
|
|
398
398
|
}
|
|
399
|
-
if ((sourceNode === null || sourceNode === void 0 ? void 0 : sourceNode.type.name) === 'taskList' && sliceFrom > 0 && expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
400
|
-
sliceFrom = sliceFrom - 1;
|
|
401
|
-
}
|
|
402
399
|
|
|
403
400
|
// Currently we don't support breakout mark for children nodes of bodiedSyncBlock node
|
|
404
401
|
// Hence strip out the mark for now
|
|
@@ -1,39 +1,54 @@
|
|
|
1
|
-
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
2
1
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
2
|
import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
4
3
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
import { createPreservedSelection } from '../../pm-plugins/utils/selection';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Gets the current node position and bounds from the selection using the preserved selection logic.
|
|
8
|
+
* This ensures consistency with how the block controls plugin handles selection boundaries.
|
|
9
|
+
*
|
|
10
|
+
* Special handling for tables: When moving a table as a block, we need the outer table node's
|
|
11
|
+
* position, not the internal cell selection that createPreservedSelection returns.
|
|
12
|
+
*
|
|
13
|
+
* @param selection The current editor selection
|
|
14
|
+
* @returns An object with from and to positions, or undefined if selection is invalid
|
|
15
|
+
*/
|
|
16
|
+
export const getNodeBoundsFromSelection = selection => {
|
|
17
|
+
// Special case: if a table is selected, we want to move the entire table node
|
|
18
|
+
const tableInfo = findTable(selection);
|
|
19
|
+
if (tableInfo && isTableSelected(selection)) {
|
|
20
|
+
const tablePos = tableInfo.pos;
|
|
21
|
+
const tableTo = tablePos + tableInfo.node.nodeSize;
|
|
22
|
+
return {
|
|
23
|
+
from: tablePos,
|
|
24
|
+
to: tableTo
|
|
25
|
+
};
|
|
14
26
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (selection.$from.depth > 0) {
|
|
29
|
-
currentNodePos = getNestedNodePosition({
|
|
30
|
-
selection,
|
|
31
|
-
schema,
|
|
32
|
-
resolve
|
|
33
|
-
});
|
|
27
|
+
|
|
28
|
+
// Special case: if a media node (file) is selected, we need to get the parent mediaGroup
|
|
29
|
+
// This handles the case where clicking on a file creates a NodeSelection of the media node
|
|
30
|
+
// but we want to move the entire mediaGroup that wraps it
|
|
31
|
+
if (selection instanceof NodeSelection && selection.node.type.name === 'media' && selection.node.attrs.type === 'file' && expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
32
|
+
// The media node is wrapped in a mediaGroup, so we need to get the parent position
|
|
33
|
+
const mediaGroupPos = selection.$from.pos - 1;
|
|
34
|
+
const mediaGroupNode = selection.$from.doc.nodeAt(mediaGroupPos);
|
|
35
|
+
if (mediaGroupNode && mediaGroupNode.type.name === 'mediaGroup') {
|
|
36
|
+
return {
|
|
37
|
+
from: mediaGroupPos,
|
|
38
|
+
to: mediaGroupPos + mediaGroupNode.nodeSize
|
|
39
|
+
};
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
|
-
|
|
42
|
+
|
|
43
|
+
// Use createPreservedSelection to get properly expanded block boundaries
|
|
44
|
+
const preservedSelection = createPreservedSelection(selection.$from, selection.$to);
|
|
45
|
+
if (!preservedSelection) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
from: preservedSelection.from,
|
|
50
|
+
to: preservedSelection.to
|
|
51
|
+
};
|
|
37
52
|
};
|
|
38
53
|
export const getPosWhenMoveNodeUp = ($currentNodePos, currentNodePos) => {
|
|
39
54
|
const nodeIndex = $currentNodePos.index();
|
|
@@ -73,19 +88,16 @@ export const getShouldMoveNode = ({
|
|
|
73
88
|
return moveToPos > -1 && tr.doc.resolve(currentNodePos).depth === tr.doc.resolve(moveToPos).depth;
|
|
74
89
|
};
|
|
75
90
|
export const canMoveNodeUpOrDown = tr => {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
schema: tr.doc.type.schema,
|
|
79
|
-
resolve: tr.doc.resolve.bind(tr.doc)
|
|
80
|
-
});
|
|
81
|
-
if (currentNodePos <= -1) {
|
|
91
|
+
const nodeBounds = getNodeBoundsFromSelection(tr.selection);
|
|
92
|
+
if (!nodeBounds || nodeBounds.from <= -1) {
|
|
82
93
|
return {
|
|
83
94
|
moveUp: false,
|
|
84
95
|
moveDown: false
|
|
85
96
|
};
|
|
86
97
|
}
|
|
98
|
+
const currentNodePos = nodeBounds.from;
|
|
87
99
|
const $currentNodePos = tr.doc.resolve(currentNodePos);
|
|
88
|
-
const nodeAfterPos =
|
|
100
|
+
const nodeAfterPos = nodeBounds.to;
|
|
89
101
|
const moveUpPos = getPosWhenMoveNodeUp($currentNodePos, currentNodePos);
|
|
90
102
|
const moveDownPos = getPosWhenMoveNodeDown({
|
|
91
103
|
$currentNodePos,
|
|
@@ -56,6 +56,11 @@ export const handleMouseOver = (view, event, api) => {
|
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
// If the editor view is not in focus when the block menu is open, do not update the drag handle
|
|
60
|
+
if (!view.hasFocus() && isMenuOpen && expValEquals('platform_editor_block_menu', 'isEnabled', true)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
// Most mouseover events don't fire during drag but some can slip through
|
|
60
65
|
// when the drag begins. This prevents those.
|
|
61
66
|
if (isDragging) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { bind } from 'bind-event-listener';
|
|
1
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
3
|
import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
|
|
3
4
|
import { key } from '../main';
|
|
4
5
|
import { createPreservedSelection, mapPreservedSelection } from '../utils/selection';
|
|
5
6
|
import { stopPreservingSelection } from './editor-commands';
|
|
6
7
|
import { selectionPreservationPluginKey } from './plugin-key';
|
|
7
|
-
import { compareSelections, getSelectionPreservationMeta, hasUserSelectionChange,
|
|
8
|
+
import { compareSelections, getSelectionPreservationMeta, hasUserSelectionChange, syncDOMSelection } from './utils';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Selection Preservation Plugin
|
|
@@ -58,7 +59,7 @@ export const createSelectionPreservationPlugin = api => () => {
|
|
|
58
59
|
newState.preservedSelection = mapPreservedSelection(newState.preservedSelection, tr);
|
|
59
60
|
}
|
|
60
61
|
if (!compareSelections(newState.preservedSelection, pluginState.preservedSelection)) {
|
|
61
|
-
if (newState
|
|
62
|
+
if (newState.preservedSelection) {
|
|
62
63
|
var _api$selection, _api$selection$comman;
|
|
63
64
|
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : (_api$selection$comman = _api$selection.commands) === null || _api$selection$comman === void 0 ? void 0 : _api$selection$comman.setBlockSelection(newState.preservedSelection));
|
|
64
65
|
} else {
|
|
@@ -77,8 +78,8 @@ export const createSelectionPreservationPlugin = api => () => {
|
|
|
77
78
|
return null;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
// Auto-stop if user explicitly changes selection
|
|
81
|
-
if (hasUserSelectionChange(transactions)
|
|
81
|
+
// Auto-stop if user explicitly changes selection
|
|
82
|
+
if (hasUserSelectionChange(transactions)) {
|
|
82
83
|
return stopPreservingSelection({
|
|
83
84
|
tr: newState.tr
|
|
84
85
|
});
|
|
@@ -98,10 +99,52 @@ export const createSelectionPreservationPlugin = api => () => {
|
|
|
98
99
|
}
|
|
99
100
|
return newState.tr.setSelection(newSelection);
|
|
100
101
|
},
|
|
101
|
-
view() {
|
|
102
|
+
view(initialView) {
|
|
103
|
+
let view = initialView;
|
|
104
|
+
const unbindDocumentMouseDown = bind(document, {
|
|
105
|
+
type: 'mousedown',
|
|
106
|
+
listener: e => {
|
|
107
|
+
if (!(e.target instanceof HTMLElement)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const {
|
|
111
|
+
preservedSelection
|
|
112
|
+
} = selectionPreservationPluginKey.getState(view.state) || {};
|
|
113
|
+
|
|
114
|
+
// If there is no current preserved selection or the editor is not focused, do nothing
|
|
115
|
+
if (!preservedSelection) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const clickedDragHandle = !!e.target.closest(DRAG_HANDLE_SELECTOR);
|
|
119
|
+
|
|
120
|
+
// When mouse down on a drag handle we continue preserving the selection
|
|
121
|
+
if (clickedDragHandle) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const clickedOutsideEditor = !e.target.closest('.ProseMirror');
|
|
125
|
+
|
|
126
|
+
// When mouse down outside the editor continue to preserve the selection
|
|
127
|
+
if (clickedOutsideEditor) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Otherwise mouse down anywhere else in the editor stops preserving the selection
|
|
132
|
+
const tr = view.state.tr;
|
|
133
|
+
stopPreservingSelection({
|
|
134
|
+
tr
|
|
135
|
+
});
|
|
136
|
+
view.dispatch(tr);
|
|
137
|
+
},
|
|
138
|
+
// Use capture phase to stop preservation before appendTransaction runs,
|
|
139
|
+
// preventing unwanted selection restoration when the user clicks into the editor.
|
|
140
|
+
options: {
|
|
141
|
+
capture: true
|
|
142
|
+
}
|
|
143
|
+
});
|
|
102
144
|
return {
|
|
103
|
-
update(
|
|
145
|
+
update(updateView, prevState) {
|
|
104
146
|
var _selectionPreservatio, _selectionPreservatio2, _key$getState, _key$getState2;
|
|
147
|
+
view = updateView;
|
|
105
148
|
const prevPreservedSelection = (_selectionPreservatio = selectionPreservationPluginKey.getState(prevState)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection;
|
|
106
149
|
const currPreservedSelection = (_selectionPreservatio2 = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio2 === void 0 ? void 0 : _selectionPreservatio2.preservedSelection;
|
|
107
150
|
const prevActiveNode = (_key$getState = key.getState(prevState)) === null || _key$getState === void 0 ? void 0 : _key$getState.activeNode;
|
|
@@ -109,34 +152,13 @@ export const createSelectionPreservationPlugin = api => () => {
|
|
|
109
152
|
if (currPreservedSelection && view.hasFocus() && (!compareSelections(prevPreservedSelection, currPreservedSelection) || prevActiveNode !== currActiveNode)) {
|
|
110
153
|
syncDOMSelection(view.state.selection);
|
|
111
154
|
}
|
|
155
|
+
},
|
|
156
|
+
destroy() {
|
|
157
|
+
unbindDocumentMouseDown();
|
|
112
158
|
}
|
|
113
159
|
};
|
|
114
160
|
},
|
|
115
161
|
props: {
|
|
116
|
-
handleClick: (view, pos, event) => {
|
|
117
|
-
const {
|
|
118
|
-
preservedSelection
|
|
119
|
-
} = selectionPreservationPluginKey.getState(view.state) || {};
|
|
120
|
-
|
|
121
|
-
// If there is no current preserved selection, do nothing
|
|
122
|
-
if (!preservedSelection) {
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
const clickedDragHandle = event.target instanceof HTMLElement && event.target.closest(DRAG_HANDLE_SELECTOR);
|
|
126
|
-
|
|
127
|
-
// When clicking a drag handle we continue preserving the selection
|
|
128
|
-
if (!clickedDragHandle) {
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Otherwise clicking anywhere else in the editor stops preserving the selection
|
|
133
|
-
const tr = view.state.tr;
|
|
134
|
-
stopPreservingSelection({
|
|
135
|
-
tr
|
|
136
|
-
});
|
|
137
|
-
view.dispatch(tr);
|
|
138
|
-
return false;
|
|
139
|
-
},
|
|
140
162
|
handleKeyDown: (view, event) => {
|
|
141
163
|
var _api$core, _api$blockControls, _api$blockControls$co;
|
|
142
164
|
const {
|
|
@@ -12,19 +12,6 @@ export const getSelectionPreservationMeta = tr => {
|
|
|
12
12
|
return tr.getMeta(selectionPreservationPluginKey);
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Checks if the current selection is within a code block.
|
|
17
|
-
*
|
|
18
|
-
* @param selection The current selection to check.
|
|
19
|
-
* @returns True if the selection is within a code block, otherwise false.
|
|
20
|
-
*/
|
|
21
|
-
export const isSelectionWithinCodeBlock = ({
|
|
22
|
-
$from,
|
|
23
|
-
$to
|
|
24
|
-
}) => {
|
|
25
|
-
return $from.sameParent($to) && $from.parent.type.name === 'codeBlock';
|
|
26
|
-
};
|
|
27
|
-
|
|
28
15
|
/**
|
|
29
16
|
* Compares two selections for equality based on their from and to positions.
|
|
30
17
|
*
|
|
@@ -7,7 +7,7 @@ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equ
|
|
|
7
7
|
import { key } from '../pm-plugins/main';
|
|
8
8
|
import { mapPreservedSelection } from '../pm-plugins/utils/selection';
|
|
9
9
|
import { moveNode } from './move-node';
|
|
10
|
-
import { canMoveNodeUpOrDown,
|
|
10
|
+
import { canMoveNodeUpOrDown, getNodeBoundsFromSelection } from './utils/move-node-utils';
|
|
11
11
|
var getSelectionToIndex = function getSelectionToIndex(fromIndex, $to, depth) {
|
|
12
12
|
var toIndex = $to.index(depth);
|
|
13
13
|
var toIndexAfter = $to.indexAfter(depth);
|
|
@@ -29,12 +29,12 @@ export var moveNodeWithBlockMenu = function moveNodeWithBlockMenu(api, direction
|
|
|
29
29
|
var preservedSelection = api === null || api === void 0 || (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection;
|
|
30
30
|
var selection = preservedSelection !== null && preservedSelection !== void 0 ? preservedSelection : tr.selection;
|
|
31
31
|
|
|
32
|
-
//
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
// Use getNodeBoundsFromSelection to get the proper block boundaries
|
|
33
|
+
var nodeBounds = getNodeBoundsFromSelection(selection);
|
|
34
|
+
if (!nodeBounds) {
|
|
35
|
+
return tr;
|
|
36
|
+
}
|
|
37
|
+
var currentNodePos = nodeBounds.from;
|
|
38
38
|
var $from = selection.$from,
|
|
39
39
|
$to = selection.$to;
|
|
40
40
|
var depth = tr.doc.resolve(currentNodePos).depth;
|
|
@@ -388,9 +388,6 @@ export var moveNode = function moveNode(api) {
|
|
|
388
388
|
if (!convertedNode) {
|
|
389
389
|
return tr;
|
|
390
390
|
}
|
|
391
|
-
if ((sourceNode === null || sourceNode === void 0 ? void 0 : sourceNode.type.name) === 'taskList' && sliceFrom > 0 && expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
392
|
-
sliceFrom = sliceFrom - 1;
|
|
393
|
-
}
|
|
394
391
|
|
|
395
392
|
// Currently we don't support breakout mark for children nodes of bodiedSyncBlock node
|
|
396
393
|
// Hence strip out the mark for now
|
|
@@ -1,38 +1,54 @@
|
|
|
1
|
-
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
2
1
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
2
|
import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
4
3
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
import { createPreservedSelection } from '../../pm-plugins/utils/selection';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Gets the current node position and bounds from the selection using the preserved selection logic.
|
|
8
|
+
* This ensures consistency with how the block controls plugin handles selection boundaries.
|
|
9
|
+
*
|
|
10
|
+
* Special handling for tables: When moving a table as a block, we need the outer table node's
|
|
11
|
+
* position, not the internal cell selection that createPreservedSelection returns.
|
|
12
|
+
*
|
|
13
|
+
* @param selection The current editor selection
|
|
14
|
+
* @returns An object with from and to positions, or undefined if selection is invalid
|
|
15
|
+
*/
|
|
16
|
+
export var getNodeBoundsFromSelection = function getNodeBoundsFromSelection(selection) {
|
|
17
|
+
// Special case: if a table is selected, we want to move the entire table node
|
|
18
|
+
var tableInfo = findTable(selection);
|
|
19
|
+
if (tableInfo && isTableSelected(selection)) {
|
|
20
|
+
var tablePos = tableInfo.pos;
|
|
21
|
+
var tableTo = tablePos + tableInfo.node.nodeSize;
|
|
22
|
+
return {
|
|
23
|
+
from: tablePos,
|
|
24
|
+
to: tableTo
|
|
25
|
+
};
|
|
13
26
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (selection.$from.depth > 0) {
|
|
28
|
-
currentNodePos = getNestedNodePosition({
|
|
29
|
-
selection: selection,
|
|
30
|
-
schema: schema,
|
|
31
|
-
resolve: resolve
|
|
32
|
-
});
|
|
27
|
+
|
|
28
|
+
// Special case: if a media node (file) is selected, we need to get the parent mediaGroup
|
|
29
|
+
// This handles the case where clicking on a file creates a NodeSelection of the media node
|
|
30
|
+
// but we want to move the entire mediaGroup that wraps it
|
|
31
|
+
if (selection instanceof NodeSelection && selection.node.type.name === 'media' && selection.node.attrs.type === 'file' && expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
32
|
+
// The media node is wrapped in a mediaGroup, so we need to get the parent position
|
|
33
|
+
var mediaGroupPos = selection.$from.pos - 1;
|
|
34
|
+
var mediaGroupNode = selection.$from.doc.nodeAt(mediaGroupPos);
|
|
35
|
+
if (mediaGroupNode && mediaGroupNode.type.name === 'mediaGroup') {
|
|
36
|
+
return {
|
|
37
|
+
from: mediaGroupPos,
|
|
38
|
+
to: mediaGroupPos + mediaGroupNode.nodeSize
|
|
39
|
+
};
|
|
33
40
|
}
|
|
34
41
|
}
|
|
35
|
-
|
|
42
|
+
|
|
43
|
+
// Use createPreservedSelection to get properly expanded block boundaries
|
|
44
|
+
var preservedSelection = createPreservedSelection(selection.$from, selection.$to);
|
|
45
|
+
if (!preservedSelection) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
from: preservedSelection.from,
|
|
50
|
+
to: preservedSelection.to
|
|
51
|
+
};
|
|
36
52
|
};
|
|
37
53
|
export var getPosWhenMoveNodeUp = function getPosWhenMoveNodeUp($currentNodePos, currentNodePos) {
|
|
38
54
|
var nodeIndex = $currentNodePos.index();
|
|
@@ -42,10 +58,10 @@ export var getPosWhenMoveNodeUp = function getPosWhenMoveNodeUp($currentNodePos,
|
|
|
42
58
|
}
|
|
43
59
|
return nodeBefore ? currentNodePos - nodeBefore.nodeSize : -1;
|
|
44
60
|
};
|
|
45
|
-
export var getPosWhenMoveNodeDown = function getPosWhenMoveNodeDown(
|
|
46
|
-
var $currentNodePos =
|
|
47
|
-
nodeAfterPos =
|
|
48
|
-
tr =
|
|
61
|
+
export var getPosWhenMoveNodeDown = function getPosWhenMoveNodeDown(_ref) {
|
|
62
|
+
var $currentNodePos = _ref.$currentNodePos,
|
|
63
|
+
nodeAfterPos = _ref.nodeAfterPos,
|
|
64
|
+
tr = _ref.tr;
|
|
49
65
|
var endOfDoc = $currentNodePos.end();
|
|
50
66
|
if (nodeAfterPos > endOfDoc) {
|
|
51
67
|
return -1;
|
|
@@ -62,27 +78,24 @@ export var getPosWhenMoveNodeDown = function getPosWhenMoveNodeDown(_ref2) {
|
|
|
62
78
|
// if not the last node, move to the end of the next node
|
|
63
79
|
return nodeAfter ? nodeAfterPos + nodeAfter.nodeSize : -1;
|
|
64
80
|
};
|
|
65
|
-
export var getShouldMoveNode = function getShouldMoveNode(
|
|
66
|
-
var currentNodePos =
|
|
67
|
-
moveToPos =
|
|
68
|
-
tr =
|
|
81
|
+
export var getShouldMoveNode = function getShouldMoveNode(_ref2) {
|
|
82
|
+
var currentNodePos = _ref2.currentNodePos,
|
|
83
|
+
moveToPos = _ref2.moveToPos,
|
|
84
|
+
tr = _ref2.tr;
|
|
69
85
|
// only move the node if the destination is at the same depth, not support moving a nested node to a parent node
|
|
70
86
|
return moveToPos > -1 && tr.doc.resolve(currentNodePos).depth === tr.doc.resolve(moveToPos).depth;
|
|
71
87
|
};
|
|
72
88
|
export var canMoveNodeUpOrDown = function canMoveNodeUpOrDown(tr) {
|
|
73
|
-
var
|
|
74
|
-
|
|
75
|
-
schema: tr.doc.type.schema,
|
|
76
|
-
resolve: tr.doc.resolve.bind(tr.doc)
|
|
77
|
-
});
|
|
78
|
-
if (currentNodePos <= -1) {
|
|
89
|
+
var nodeBounds = getNodeBoundsFromSelection(tr.selection);
|
|
90
|
+
if (!nodeBounds || nodeBounds.from <= -1) {
|
|
79
91
|
return {
|
|
80
92
|
moveUp: false,
|
|
81
93
|
moveDown: false
|
|
82
94
|
};
|
|
83
95
|
}
|
|
96
|
+
var currentNodePos = nodeBounds.from;
|
|
84
97
|
var $currentNodePos = tr.doc.resolve(currentNodePos);
|
|
85
|
-
var nodeAfterPos =
|
|
98
|
+
var nodeAfterPos = nodeBounds.to;
|
|
86
99
|
var moveUpPos = getPosWhenMoveNodeUp($currentNodePos, currentNodePos);
|
|
87
100
|
var moveDownPos = getPosWhenMoveNodeDown({
|
|
88
101
|
$currentNodePos: $currentNodePos,
|
|
@@ -57,6 +57,11 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
|
|
|
57
57
|
return false;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// If the editor view is not in focus when the block menu is open, do not update the drag handle
|
|
61
|
+
if (!view.hasFocus() && isMenuOpen && expValEquals('platform_editor_block_menu', 'isEnabled', true)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
// Most mouseover events don't fire during drag but some can slip through
|
|
61
66
|
// when the drag begins. This prevents those.
|
|
62
67
|
if (isDragging) {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
import { bind } from 'bind-event-listener';
|
|
4
5
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
6
|
import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
|
|
6
7
|
import { key } from '../main';
|
|
7
8
|
import { createPreservedSelection, mapPreservedSelection } from '../utils/selection';
|
|
8
9
|
import { stopPreservingSelection } from './editor-commands';
|
|
9
10
|
import { selectionPreservationPluginKey } from './plugin-key';
|
|
10
|
-
import { compareSelections, getSelectionPreservationMeta, hasUserSelectionChange,
|
|
11
|
+
import { compareSelections, getSelectionPreservationMeta, hasUserSelectionChange, syncDOMSelection } from './utils';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Selection Preservation Plugin
|
|
@@ -60,7 +61,7 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
|
|
|
60
61
|
newState.preservedSelection = mapPreservedSelection(newState.preservedSelection, tr);
|
|
61
62
|
}
|
|
62
63
|
if (!compareSelections(newState.preservedSelection, pluginState.preservedSelection)) {
|
|
63
|
-
if (newState
|
|
64
|
+
if (newState.preservedSelection) {
|
|
64
65
|
var _api$selection;
|
|
65
66
|
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.commands) === null || _api$selection === void 0 ? void 0 : _api$selection.setBlockSelection(newState.preservedSelection));
|
|
66
67
|
} else {
|
|
@@ -79,8 +80,8 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
|
|
|
79
80
|
return null;
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
// Auto-stop if user explicitly changes selection
|
|
83
|
-
if (hasUserSelectionChange(transactions)
|
|
83
|
+
// Auto-stop if user explicitly changes selection
|
|
84
|
+
if (hasUserSelectionChange(transactions)) {
|
|
84
85
|
return stopPreservingSelection({
|
|
85
86
|
tr: newState.tr
|
|
86
87
|
});
|
|
@@ -100,10 +101,51 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
|
|
|
100
101
|
}
|
|
101
102
|
return newState.tr.setSelection(newSelection);
|
|
102
103
|
},
|
|
103
|
-
view: function view() {
|
|
104
|
+
view: function view(initialView) {
|
|
105
|
+
var view = initialView;
|
|
106
|
+
var unbindDocumentMouseDown = bind(document, {
|
|
107
|
+
type: 'mousedown',
|
|
108
|
+
listener: function listener(e) {
|
|
109
|
+
if (!(e.target instanceof HTMLElement)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
var _ref = selectionPreservationPluginKey.getState(view.state) || {},
|
|
113
|
+
preservedSelection = _ref.preservedSelection;
|
|
114
|
+
|
|
115
|
+
// If there is no current preserved selection or the editor is not focused, do nothing
|
|
116
|
+
if (!preservedSelection) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
var clickedDragHandle = !!e.target.closest(DRAG_HANDLE_SELECTOR);
|
|
120
|
+
|
|
121
|
+
// When mouse down on a drag handle we continue preserving the selection
|
|
122
|
+
if (clickedDragHandle) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
var clickedOutsideEditor = !e.target.closest('.ProseMirror');
|
|
126
|
+
|
|
127
|
+
// When mouse down outside the editor continue to preserve the selection
|
|
128
|
+
if (clickedOutsideEditor) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Otherwise mouse down anywhere else in the editor stops preserving the selection
|
|
133
|
+
var tr = view.state.tr;
|
|
134
|
+
stopPreservingSelection({
|
|
135
|
+
tr: tr
|
|
136
|
+
});
|
|
137
|
+
view.dispatch(tr);
|
|
138
|
+
},
|
|
139
|
+
// Use capture phase to stop preservation before appendTransaction runs,
|
|
140
|
+
// preventing unwanted selection restoration when the user clicks into the editor.
|
|
141
|
+
options: {
|
|
142
|
+
capture: true
|
|
143
|
+
}
|
|
144
|
+
});
|
|
104
145
|
return {
|
|
105
|
-
update: function update(
|
|
146
|
+
update: function update(updateView, prevState) {
|
|
106
147
|
var _selectionPreservatio, _selectionPreservatio2, _key$getState, _key$getState2;
|
|
148
|
+
view = updateView;
|
|
107
149
|
var prevPreservedSelection = (_selectionPreservatio = selectionPreservationPluginKey.getState(prevState)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection;
|
|
108
150
|
var currPreservedSelection = (_selectionPreservatio2 = selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio2 === void 0 ? void 0 : _selectionPreservatio2.preservedSelection;
|
|
109
151
|
var prevActiveNode = (_key$getState = key.getState(prevState)) === null || _key$getState === void 0 ? void 0 : _key$getState.activeNode;
|
|
@@ -111,33 +153,13 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
|
|
|
111
153
|
if (currPreservedSelection && view.hasFocus() && (!compareSelections(prevPreservedSelection, currPreservedSelection) || prevActiveNode !== currActiveNode)) {
|
|
112
154
|
syncDOMSelection(view.state.selection);
|
|
113
155
|
}
|
|
156
|
+
},
|
|
157
|
+
destroy: function destroy() {
|
|
158
|
+
unbindDocumentMouseDown();
|
|
114
159
|
}
|
|
115
160
|
};
|
|
116
161
|
},
|
|
117
162
|
props: {
|
|
118
|
-
handleClick: function handleClick(view, pos, event) {
|
|
119
|
-
var _ref = selectionPreservationPluginKey.getState(view.state) || {},
|
|
120
|
-
preservedSelection = _ref.preservedSelection;
|
|
121
|
-
|
|
122
|
-
// If there is no current preserved selection, do nothing
|
|
123
|
-
if (!preservedSelection) {
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
var clickedDragHandle = event.target instanceof HTMLElement && event.target.closest(DRAG_HANDLE_SELECTOR);
|
|
127
|
-
|
|
128
|
-
// When clicking a drag handle we continue preserving the selection
|
|
129
|
-
if (!clickedDragHandle) {
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Otherwise clicking anywhere else in the editor stops preserving the selection
|
|
134
|
-
var tr = view.state.tr;
|
|
135
|
-
stopPreservingSelection({
|
|
136
|
-
tr: tr
|
|
137
|
-
});
|
|
138
|
-
view.dispatch(tr);
|
|
139
|
-
return false;
|
|
140
|
-
},
|
|
141
163
|
handleKeyDown: function handleKeyDown(view, event) {
|
|
142
164
|
var _api$core, _api$blockControls;
|
|
143
165
|
var _ref2 = selectionPreservationPluginKey.getState(view.state) || {},
|
|
@@ -14,18 +14,6 @@ export var getSelectionPreservationMeta = function getSelectionPreservationMeta(
|
|
|
14
14
|
return tr.getMeta(selectionPreservationPluginKey);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* Checks if the current selection is within a code block.
|
|
19
|
-
*
|
|
20
|
-
* @param selection The current selection to check.
|
|
21
|
-
* @returns True if the selection is within a code block, otherwise false.
|
|
22
|
-
*/
|
|
23
|
-
export var isSelectionWithinCodeBlock = function isSelectionWithinCodeBlock(_ref) {
|
|
24
|
-
var $from = _ref.$from,
|
|
25
|
-
$to = _ref.$to;
|
|
26
|
-
return $from.sameParent($to) && $from.parent.type.name === 'codeBlock';
|
|
27
|
-
};
|
|
28
|
-
|
|
29
17
|
/**
|
|
30
18
|
* Compares two selections for equality based on their from and to positions.
|
|
31
19
|
*
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import type { ResolvedPos
|
|
2
|
-
import type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { type Selection, type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
/**
|
|
4
|
+
* Gets the current node position and bounds from the selection using the preserved selection logic.
|
|
5
|
+
* This ensures consistency with how the block controls plugin handles selection boundaries.
|
|
6
|
+
*
|
|
7
|
+
* Special handling for tables: When moving a table as a block, we need the outer table node's
|
|
8
|
+
* position, not the internal cell selection that createPreservedSelection returns.
|
|
9
|
+
*
|
|
10
|
+
* @param selection The current editor selection
|
|
11
|
+
* @returns An object with from and to positions, or undefined if selection is invalid
|
|
12
|
+
*/
|
|
13
|
+
export declare const getNodeBoundsFromSelection: (selection: Selection) => {
|
|
14
|
+
from: number;
|
|
15
|
+
to: number;
|
|
16
|
+
} | undefined;
|
|
9
17
|
export declare const getPosWhenMoveNodeUp: ($currentNodePos: ResolvedPos, currentNodePos: number) => number;
|
|
10
18
|
export declare const getPosWhenMoveNodeDown: ({ $currentNodePos, nodeAfterPos, tr, }: {
|
|
11
19
|
$currentNodePos: ResolvedPos;
|
|
@@ -8,13 +8,6 @@ import type { SelectionPreservationMeta } from './types';
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const hasUserSelectionChange: (transactions: readonly Transaction[]) => boolean;
|
|
10
10
|
export declare const getSelectionPreservationMeta: (tr: Transaction | ReadonlyTransaction) => SelectionPreservationMeta | undefined;
|
|
11
|
-
/**
|
|
12
|
-
* Checks if the current selection is within a code block.
|
|
13
|
-
*
|
|
14
|
-
* @param selection The current selection to check.
|
|
15
|
-
* @returns True if the selection is within a code block, otherwise false.
|
|
16
|
-
*/
|
|
17
|
-
export declare const isSelectionWithinCodeBlock: ({ $from, $to }: Selection) => boolean;
|
|
18
11
|
/**
|
|
19
12
|
* Compares two selections for equality based on their from and to positions.
|
|
20
13
|
*
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import type { ResolvedPos
|
|
2
|
-
import type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { type Selection, type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
/**
|
|
4
|
+
* Gets the current node position and bounds from the selection using the preserved selection logic.
|
|
5
|
+
* This ensures consistency with how the block controls plugin handles selection boundaries.
|
|
6
|
+
*
|
|
7
|
+
* Special handling for tables: When moving a table as a block, we need the outer table node's
|
|
8
|
+
* position, not the internal cell selection that createPreservedSelection returns.
|
|
9
|
+
*
|
|
10
|
+
* @param selection The current editor selection
|
|
11
|
+
* @returns An object with from and to positions, or undefined if selection is invalid
|
|
12
|
+
*/
|
|
13
|
+
export declare const getNodeBoundsFromSelection: (selection: Selection) => {
|
|
14
|
+
from: number;
|
|
15
|
+
to: number;
|
|
16
|
+
} | undefined;
|
|
9
17
|
export declare const getPosWhenMoveNodeUp: ($currentNodePos: ResolvedPos, currentNodePos: number) => number;
|
|
10
18
|
export declare const getPosWhenMoveNodeDown: ({ $currentNodePos, nodeAfterPos, tr, }: {
|
|
11
19
|
$currentNodePos: ResolvedPos;
|
|
@@ -8,13 +8,6 @@ import type { SelectionPreservationMeta } from './types';
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const hasUserSelectionChange: (transactions: readonly Transaction[]) => boolean;
|
|
10
10
|
export declare const getSelectionPreservationMeta: (tr: Transaction | ReadonlyTransaction) => SelectionPreservationMeta | undefined;
|
|
11
|
-
/**
|
|
12
|
-
* Checks if the current selection is within a code block.
|
|
13
|
-
*
|
|
14
|
-
* @param selection The current selection to check.
|
|
15
|
-
* @returns True if the selection is within a code block, otherwise false.
|
|
16
|
-
*/
|
|
17
|
-
export declare const isSelectionWithinCodeBlock: ({ $from, $to }: Selection) => boolean;
|
|
18
11
|
/**
|
|
19
12
|
* Compares two selections for equality based on their from and to positions.
|
|
20
13
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-controls",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.11",
|
|
4
4
|
"description": "Block controls plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^3.2.0",
|
|
55
55
|
"@atlaskit/primitives": "^17.0.0",
|
|
56
56
|
"@atlaskit/theme": "^21.0.0",
|
|
57
|
-
"@atlaskit/tmp-editor-statsig": "^16.
|
|
57
|
+
"@atlaskit/tmp-editor-statsig": "^16.19.0",
|
|
58
58
|
"@atlaskit/tokens": "^9.1.0",
|
|
59
59
|
"@atlaskit/tooltip": "^20.14.0",
|
|
60
60
|
"@babel/runtime": "^7.0.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"uuid": "^3.1.0"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@atlaskit/editor-common": "^111.
|
|
69
|
+
"@atlaskit/editor-common": "^111.8.0",
|
|
70
70
|
"react": "^18.2.0",
|
|
71
71
|
"react-dom": "^18.2.0",
|
|
72
72
|
"react-intl-next": "npm:react-intl@^5.18.1"
|