@atlaskit/editor-plugin-table 10.4.5 → 10.4.7
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 +15 -0
- package/dist/cjs/pm-plugins/commands/go-to-next-cell.js +96 -6
- package/dist/cjs/pm-plugins/keymap.js +9 -0
- package/dist/es2019/pm-plugins/commands/go-to-next-cell.js +97 -6
- package/dist/es2019/pm-plugins/keymap.js +10 -1
- package/dist/esm/pm-plugins/commands/go-to-next-cell.js +96 -6
- package/dist/esm/pm-plugins/keymap.js +10 -1
- package/dist/types/pm-plugins/commands/go-to-next-cell.d.ts +6 -0
- package/dist/types-ts4.5/pm-plugins/commands/go-to-next-cell.d.ts +6 -0
- package/package.json +3 -3
- package/src/pm-plugins/commands/go-to-next-cell.ts +129 -4
- package/src/pm-plugins/keymap.ts +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-table
|
|
2
2
|
|
|
3
|
+
## 10.4.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 10.4.6
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#124950](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/124950)
|
|
14
|
+
[`45961c4f4a9a3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/45961c4f4a9a3) -
|
|
15
|
+
[ux] ED-25485 Fixes issue where up/down arrow keys would move to the wrong cell in a table if
|
|
16
|
+
there was a node selection inside the table.
|
|
17
|
+
|
|
3
18
|
## 10.4.5
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.goToNextCell = void 0;
|
|
6
|
+
exports.goToNextCellVertical = exports.goToNextCell = void 0;
|
|
7
7
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
8
|
+
var _nesting = require("@atlaskit/editor-common/nesting");
|
|
9
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
8
10
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
9
11
|
var _tableMap = require("@atlaskit/editor-tables/table-map");
|
|
10
12
|
var _utils2 = require("@atlaskit/editor-tables/utils");
|
|
11
13
|
var _pluginFactory = require("../plugin-factory");
|
|
12
14
|
var _columnResize = require("./column-resize");
|
|
13
15
|
var _commandsWithAnalytics = require("./commands-with-analytics");
|
|
14
|
-
// #region Constants
|
|
15
|
-
|
|
16
16
|
var TAB_FORWARD_DIRECTION = 1;
|
|
17
17
|
var TAB_BACKWARD_DIRECTION = -1;
|
|
18
18
|
var goToNextCell = exports.goToNextCell = function goToNextCell(editorAnalyticsAPI, ariaNotify, getIntl) {
|
|
@@ -41,7 +41,7 @@ var goToNextCell = exports.goToNextCell = function goToNextCell(editorAnalyticsA
|
|
|
41
41
|
var firstCellPos = map.positionAt(0, 0, table.node) + table.start;
|
|
42
42
|
var lastCellPos = map.positionAt(map.height - 1, map.width - 1, table.node) + table.start;
|
|
43
43
|
|
|
44
|
-
//
|
|
44
|
+
// When tabbing backwards at first cell (top left), insert row at the start of table
|
|
45
45
|
if (firstCellPos === cell.pos && direction === TAB_BACKWARD_DIRECTION) {
|
|
46
46
|
(0, _commandsWithAnalytics.insertRowWithAnalytics)(editorAnalyticsAPI)(_analytics.INPUT_METHOD.KEYBOARD, {
|
|
47
47
|
index: 0,
|
|
@@ -50,7 +50,7 @@ var goToNextCell = exports.goToNextCell = function goToNextCell(editorAnalyticsA
|
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
//
|
|
53
|
+
// When tabbing forwards at last cell (bottom right), insert row at the end of table
|
|
54
54
|
if (lastCellPos === cell.pos && direction === TAB_FORWARD_DIRECTION) {
|
|
55
55
|
(0, _commandsWithAnalytics.insertRowWithAnalytics)(editorAnalyticsAPI)(_analytics.INPUT_METHOD.KEYBOARD, {
|
|
56
56
|
index: map.height,
|
|
@@ -64,4 +64,94 @@ var goToNextCell = exports.goToNextCell = function goToNextCell(editorAnalyticsA
|
|
|
64
64
|
return true;
|
|
65
65
|
};
|
|
66
66
|
};
|
|
67
|
-
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Moves the cursor vertically from a NodeSelection within a table cell.
|
|
71
|
+
* - If content exists above/below within the cell, lets ProseMirror handle it.
|
|
72
|
+
* - Otherwise, moves to the next cell (down to start, up to last line).
|
|
73
|
+
*/
|
|
74
|
+
var goToNextCellVertical = exports.goToNextCellVertical = function goToNextCellVertical(direction) {
|
|
75
|
+
return function (state, dispatch) {
|
|
76
|
+
var selection = state.selection;
|
|
77
|
+
var nestedTableSelection = (0, _nesting.isSelectionTableNestedInTable)(state);
|
|
78
|
+
if (!(selection instanceof _state.NodeSelection) && !nestedTableSelection) {
|
|
79
|
+
return false; // Let ProseMirror handle other selection types
|
|
80
|
+
}
|
|
81
|
+
var table = (0, _utils2.findTable)(selection);
|
|
82
|
+
var cell = (0, _utils2.findCellClosestToPos)(state.doc.resolve(selection.from));
|
|
83
|
+
var selectionPos = selection.from;
|
|
84
|
+
|
|
85
|
+
// Handle when we have nested table fully selected
|
|
86
|
+
if (table && nestedTableSelection && (0, _utils2.isTableSelected)(selection)) {
|
|
87
|
+
var parentTablePos = table.pos;
|
|
88
|
+
table = (0, _utils2.findTableClosestToPos)(state.doc.resolve(parentTablePos));
|
|
89
|
+
cell = (0, _utils2.findCellClosestToPos)(state.doc.resolve(parentTablePos));
|
|
90
|
+
selectionPos = parentTablePos;
|
|
91
|
+
}
|
|
92
|
+
if (!table || !cell || !cell.pos) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
var _state$schema$nodes2 = state.schema.nodes,
|
|
96
|
+
tableCell = _state$schema$nodes2.tableCell,
|
|
97
|
+
tableHeader = _state$schema$nodes2.tableHeader;
|
|
98
|
+
|
|
99
|
+
// Let ProseMirror handle movement within the cell if content exists above/below
|
|
100
|
+
if (cellHasContentInDirection(cell.node, cell.pos, selectionPos, direction)) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Move to the next cell vertically
|
|
105
|
+
var map = _tableMap.TableMap.get(table.node);
|
|
106
|
+
var nextCellPos = map.nextCell(cell.pos - table.start, 'vert', direction);
|
|
107
|
+
if (dispatch && nextCellPos) {
|
|
108
|
+
var _$nextCell$nodeAfter, _$nextCell$nodeAfter2;
|
|
109
|
+
var nextCellStart = table.start + nextCellPos;
|
|
110
|
+
var $nextCell = state.doc.resolve(nextCellStart);
|
|
111
|
+
if ((_$nextCell$nodeAfter = $nextCell.nodeAfter) !== null && _$nextCell$nodeAfter !== void 0 && _$nextCell$nodeAfter.type && [tableCell, tableHeader].includes((_$nextCell$nodeAfter2 = $nextCell.nodeAfter) === null || _$nextCell$nodeAfter2 === void 0 ? void 0 : _$nextCell$nodeAfter2.type)) {
|
|
112
|
+
var contentPos = getTargetPositionInNextCell($nextCell.nodeAfter, nextCellStart, direction);
|
|
113
|
+
dispatch(state.tr.setSelection(_state.TextSelection.create(state.doc, contentPos)));
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return false; // No next cell found
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
function cellHasContentInDirection(cellNode, cellPos, selectionPos, direction) {
|
|
122
|
+
var hasContent = false;
|
|
123
|
+
cellNode.content.forEach(function (node, offset) {
|
|
124
|
+
var nodeStart = cellPos + 1 + offset;
|
|
125
|
+
var nodeEnd = nodeStart + node.nodeSize;
|
|
126
|
+
if (direction === 1 && nodeStart > selectionPos && node.isBlock) {
|
|
127
|
+
hasContent = true; // Content below
|
|
128
|
+
} else if (direction === -1 && nodeEnd <= selectionPos && node.isBlock) {
|
|
129
|
+
hasContent = true; // Content above
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return hasContent;
|
|
133
|
+
}
|
|
134
|
+
function getTargetPositionInNextCell(cellNode, nextCellStart, direction) {
|
|
135
|
+
var contentPos = nextCellStart + 1; // Default: just inside the cell
|
|
136
|
+
if (cellNode.content.size > 0) {
|
|
137
|
+
if (direction === 1) {
|
|
138
|
+
var firstChild = cellNode.firstChild;
|
|
139
|
+
if (firstChild && firstChild.isBlock) {
|
|
140
|
+
contentPos = nextCellStart + 1 + (firstChild.isLeaf ? 0 : 1); // Down: Start of first block
|
|
141
|
+
}
|
|
142
|
+
} else if (direction === -1) {
|
|
143
|
+
var lastBlock;
|
|
144
|
+
var lastOffset = 0;
|
|
145
|
+
cellNode.content.forEach(function (node, offset) {
|
|
146
|
+
if (node.isBlock) {
|
|
147
|
+
lastBlock = node;
|
|
148
|
+
lastOffset = offset;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
if (lastBlock) {
|
|
152
|
+
contentPos = nextCellStart + 1 + lastOffset + (lastBlock.isLeaf ? 0 : lastBlock.nodeSize - 1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return contentPos;
|
|
157
|
+
}
|
|
@@ -15,6 +15,7 @@ var _commandsWithAnalytics = require("../pm-plugins/drag-and-drop/commands-with-
|
|
|
15
15
|
var _commands2 = require("./commands");
|
|
16
16
|
var _columnResize = require("./commands/column-resize");
|
|
17
17
|
var _commandsWithAnalytics2 = require("./commands/commands-with-analytics");
|
|
18
|
+
var _goToNextCell = require("./commands/go-to-next-cell");
|
|
18
19
|
var _insert = require("./commands/insert");
|
|
19
20
|
function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProviderAPI, editorAnalyticsAPI, dragAndDropEnabled) {
|
|
20
21
|
var _pluginInjectionApi$a;
|
|
@@ -163,6 +164,14 @@ function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProviderAPI, e
|
|
|
163
164
|
(0, _keymaps.bindKeymapWithCommand)(
|
|
164
165
|
// Ignored via go/ees005
|
|
165
166
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
167
|
+
_keymaps.moveDown.common, (0, _goToNextCell.goToNextCellVertical)(1), list);
|
|
168
|
+
(0, _keymaps.bindKeymapWithCommand)(
|
|
169
|
+
// Ignored via go/ees005
|
|
170
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
171
|
+
_keymaps.moveUp.common, (0, _goToNextCell.goToNextCellVertical)(-1), list);
|
|
172
|
+
(0, _keymaps.bindKeymapWithCommand)(
|
|
173
|
+
// Ignored via go/ees005
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
166
175
|
_keymaps.decreaseMediaSize.common, (0, _commandsWithAnalytics2.changeColumnWidthByStepWithAnalytics)(editorAnalyticsAPI, api)(-10, getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, !!isCommentEditor, _analytics.INPUT_METHOD.SHORTCUT, ariaNotifyPlugin, getIntl), list);
|
|
167
176
|
(0, _keymaps.bindKeymapWithCommand)(
|
|
168
177
|
// Ignored via go/ees005
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// #region Constants
|
|
2
|
-
|
|
3
1
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { isSelectionTableNestedInTable } from '@atlaskit/editor-common/nesting';
|
|
3
|
+
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
5
5
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
6
|
-
import { goToNextCell as baseGotoNextCell, findTable } from '@atlaskit/editor-tables/utils';
|
|
6
|
+
import { goToNextCell as baseGotoNextCell, findCellClosestToPos, findTable, findTableClosestToPos, isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
7
7
|
import { getPluginState } from '../plugin-factory';
|
|
8
8
|
import { stopKeyboardColumnResizing } from './column-resize';
|
|
9
9
|
import { insertRowWithAnalytics } from './commands-with-analytics';
|
|
@@ -34,7 +34,7 @@ export const goToNextCell = (editorAnalyticsAPI, ariaNotify, getIntl) => directi
|
|
|
34
34
|
const firstCellPos = map.positionAt(0, 0, table.node) + table.start;
|
|
35
35
|
const lastCellPos = map.positionAt(map.height - 1, map.width - 1, table.node) + table.start;
|
|
36
36
|
|
|
37
|
-
//
|
|
37
|
+
// When tabbing backwards at first cell (top left), insert row at the start of table
|
|
38
38
|
if (firstCellPos === cell.pos && direction === TAB_BACKWARD_DIRECTION) {
|
|
39
39
|
insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.KEYBOARD, {
|
|
40
40
|
index: 0,
|
|
@@ -43,7 +43,7 @@ export const goToNextCell = (editorAnalyticsAPI, ariaNotify, getIntl) => directi
|
|
|
43
43
|
return true;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// When tabbing forwards at last cell (bottom right), insert row at the end of table
|
|
47
47
|
if (lastCellPos === cell.pos && direction === TAB_FORWARD_DIRECTION) {
|
|
48
48
|
insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.KEYBOARD, {
|
|
49
49
|
index: map.height,
|
|
@@ -55,4 +55,95 @@ export const goToNextCell = (editorAnalyticsAPI, ariaNotify, getIntl) => directi
|
|
|
55
55
|
return baseGotoNextCell(direction)(state, dispatch);
|
|
56
56
|
}
|
|
57
57
|
return true;
|
|
58
|
-
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Moves the cursor vertically from a NodeSelection within a table cell.
|
|
62
|
+
* - If content exists above/below within the cell, lets ProseMirror handle it.
|
|
63
|
+
* - Otherwise, moves to the next cell (down to start, up to last line).
|
|
64
|
+
*/
|
|
65
|
+
export const goToNextCellVertical = direction => (state, dispatch) => {
|
|
66
|
+
const {
|
|
67
|
+
selection
|
|
68
|
+
} = state;
|
|
69
|
+
const nestedTableSelection = isSelectionTableNestedInTable(state);
|
|
70
|
+
if (!(selection instanceof NodeSelection) && !nestedTableSelection) {
|
|
71
|
+
return false; // Let ProseMirror handle other selection types
|
|
72
|
+
}
|
|
73
|
+
let table = findTable(selection);
|
|
74
|
+
let cell = findCellClosestToPos(state.doc.resolve(selection.from));
|
|
75
|
+
let selectionPos = selection.from;
|
|
76
|
+
|
|
77
|
+
// Handle when we have nested table fully selected
|
|
78
|
+
if (table && nestedTableSelection && isTableSelected(selection)) {
|
|
79
|
+
const parentTablePos = table.pos;
|
|
80
|
+
table = findTableClosestToPos(state.doc.resolve(parentTablePos));
|
|
81
|
+
cell = findCellClosestToPos(state.doc.resolve(parentTablePos));
|
|
82
|
+
selectionPos = parentTablePos;
|
|
83
|
+
}
|
|
84
|
+
if (!table || !cell || !cell.pos) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const {
|
|
88
|
+
tableCell,
|
|
89
|
+
tableHeader
|
|
90
|
+
} = state.schema.nodes;
|
|
91
|
+
|
|
92
|
+
// Let ProseMirror handle movement within the cell if content exists above/below
|
|
93
|
+
if (cellHasContentInDirection(cell.node, cell.pos, selectionPos, direction)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Move to the next cell vertically
|
|
98
|
+
const map = TableMap.get(table.node);
|
|
99
|
+
const nextCellPos = map.nextCell(cell.pos - table.start, 'vert', direction);
|
|
100
|
+
if (dispatch && nextCellPos) {
|
|
101
|
+
var _$nextCell$nodeAfter, _$nextCell$nodeAfter2;
|
|
102
|
+
const nextCellStart = table.start + nextCellPos;
|
|
103
|
+
const $nextCell = state.doc.resolve(nextCellStart);
|
|
104
|
+
if ((_$nextCell$nodeAfter = $nextCell.nodeAfter) !== null && _$nextCell$nodeAfter !== void 0 && _$nextCell$nodeAfter.type && [tableCell, tableHeader].includes((_$nextCell$nodeAfter2 = $nextCell.nodeAfter) === null || _$nextCell$nodeAfter2 === void 0 ? void 0 : _$nextCell$nodeAfter2.type)) {
|
|
105
|
+
const contentPos = getTargetPositionInNextCell($nextCell.nodeAfter, nextCellStart, direction);
|
|
106
|
+
dispatch(state.tr.setSelection(TextSelection.create(state.doc, contentPos)));
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return false; // No next cell found
|
|
112
|
+
};
|
|
113
|
+
function cellHasContentInDirection(cellNode, cellPos, selectionPos, direction) {
|
|
114
|
+
let hasContent = false;
|
|
115
|
+
cellNode.content.forEach((node, offset) => {
|
|
116
|
+
const nodeStart = cellPos + 1 + offset;
|
|
117
|
+
const nodeEnd = nodeStart + node.nodeSize;
|
|
118
|
+
if (direction === 1 && nodeStart > selectionPos && node.isBlock) {
|
|
119
|
+
hasContent = true; // Content below
|
|
120
|
+
} else if (direction === -1 && nodeEnd <= selectionPos && node.isBlock) {
|
|
121
|
+
hasContent = true; // Content above
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return hasContent;
|
|
125
|
+
}
|
|
126
|
+
function getTargetPositionInNextCell(cellNode, nextCellStart, direction) {
|
|
127
|
+
let contentPos = nextCellStart + 1; // Default: just inside the cell
|
|
128
|
+
if (cellNode.content.size > 0) {
|
|
129
|
+
if (direction === 1) {
|
|
130
|
+
const firstChild = cellNode.firstChild;
|
|
131
|
+
if (firstChild && firstChild.isBlock) {
|
|
132
|
+
contentPos = nextCellStart + 1 + (firstChild.isLeaf ? 0 : 1); // Down: Start of first block
|
|
133
|
+
}
|
|
134
|
+
} else if (direction === -1) {
|
|
135
|
+
let lastBlock;
|
|
136
|
+
let lastOffset = 0;
|
|
137
|
+
cellNode.content.forEach((node, offset) => {
|
|
138
|
+
if (node.isBlock) {
|
|
139
|
+
lastBlock = node;
|
|
140
|
+
lastOffset = offset;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
if (lastBlock) {
|
|
144
|
+
contentPos = nextCellStart + 1 + lastOffset + (lastBlock.isLeaf ? 0 : lastBlock.nodeSize - 1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return contentPos;
|
|
149
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
-
import { addColumnAfter, addColumnAfterVO, addColumnBefore, addColumnBeforeVO, addRowAfter, addRowAfterVO, addRowBefore, addRowBeforeVO, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, escape, focusToContextMenuTrigger, increaseMediaSize, moveColumnLeft, moveColumnRight, moveLeft, moveRight, moveRowDown, moveRowUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
|
|
2
|
+
import { addColumnAfter, addColumnAfterVO, addColumnBefore, addColumnBeforeVO, addRowAfter, addRowAfterVO, addRowBefore, addRowBeforeVO, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, escape, focusToContextMenuTrigger, increaseMediaSize, moveColumnLeft, moveColumnRight, moveDown, moveLeft, moveRight, moveRowDown, moveRowUp, moveUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
|
|
3
3
|
import { editorCommandToPMCommand } from '@atlaskit/editor-common/preset';
|
|
4
4
|
import { chainCommands } from '@atlaskit/editor-prosemirror/commands';
|
|
5
5
|
import { keymap } from '@atlaskit/editor-prosemirror/keymap';
|
|
@@ -8,6 +8,7 @@ import { moveSourceWithAnalyticsViaShortcut } from '../pm-plugins/drag-and-drop/
|
|
|
8
8
|
import { goToNextCell, moveCursorBackward, setFocusToCellMenu } from './commands';
|
|
9
9
|
import { activateNextResizeArea, initiateKeyboardColumnResizing, stopKeyboardColumnResizing } from './commands/column-resize';
|
|
10
10
|
import { addRowAroundSelection, changeColumnWidthByStepWithAnalytics, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut, deleteTableIfSelectedWithAnalytics, emptyMultipleCellsWithAnalytics } from './commands/commands-with-analytics';
|
|
11
|
+
import { goToNextCellVertical } from './commands/go-to-next-cell';
|
|
11
12
|
import { addColumnAfter as addColumnAfterCommand, addColumnBefore as addColumnBeforeCommand, createTable, insertTableWithNestingSupport } from './commands/insert';
|
|
12
13
|
export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProviderAPI, editorAnalyticsAPI, dragAndDropEnabled, isTableScalingEnabled = false, isTableAlignmentEnabled = false, isFullWidthEnabled, pluginInjectionApi, getIntl, isTableFixedColumnWidthsOptionEnabled = false, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor, isTableResizingEnabled) {
|
|
13
14
|
var _pluginInjectionApi$a;
|
|
@@ -146,6 +147,14 @@ export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProvide
|
|
|
146
147
|
bindKeymapWithCommand(
|
|
147
148
|
// Ignored via go/ees005
|
|
148
149
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
150
|
+
moveDown.common, goToNextCellVertical(1), list);
|
|
151
|
+
bindKeymapWithCommand(
|
|
152
|
+
// Ignored via go/ees005
|
|
153
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
154
|
+
moveUp.common, goToNextCellVertical(-1), list);
|
|
155
|
+
bindKeymapWithCommand(
|
|
156
|
+
// Ignored via go/ees005
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
149
158
|
decreaseMediaSize.common, changeColumnWidthByStepWithAnalytics(editorAnalyticsAPI, api)(-10, getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, !!isCommentEditor, INPUT_METHOD.SHORTCUT, ariaNotifyPlugin, getIntl), list);
|
|
150
159
|
bindKeymapWithCommand(
|
|
151
160
|
// Ignored via go/ees005
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// #region Constants
|
|
2
|
-
|
|
3
1
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { isSelectionTableNestedInTable } from '@atlaskit/editor-common/nesting';
|
|
3
|
+
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
5
5
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
6
|
-
import { goToNextCell as baseGotoNextCell, findTable } from '@atlaskit/editor-tables/utils';
|
|
6
|
+
import { goToNextCell as baseGotoNextCell, findCellClosestToPos, findTable, findTableClosestToPos, isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
7
7
|
import { getPluginState } from '../plugin-factory';
|
|
8
8
|
import { stopKeyboardColumnResizing } from './column-resize';
|
|
9
9
|
import { insertRowWithAnalytics } from './commands-with-analytics';
|
|
@@ -35,7 +35,7 @@ export var goToNextCell = function goToNextCell(editorAnalyticsAPI, ariaNotify,
|
|
|
35
35
|
var firstCellPos = map.positionAt(0, 0, table.node) + table.start;
|
|
36
36
|
var lastCellPos = map.positionAt(map.height - 1, map.width - 1, table.node) + table.start;
|
|
37
37
|
|
|
38
|
-
//
|
|
38
|
+
// When tabbing backwards at first cell (top left), insert row at the start of table
|
|
39
39
|
if (firstCellPos === cell.pos && direction === TAB_BACKWARD_DIRECTION) {
|
|
40
40
|
insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.KEYBOARD, {
|
|
41
41
|
index: 0,
|
|
@@ -44,7 +44,7 @@ export var goToNextCell = function goToNextCell(editorAnalyticsAPI, ariaNotify,
|
|
|
44
44
|
return true;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
//
|
|
47
|
+
// When tabbing forwards at last cell (bottom right), insert row at the end of table
|
|
48
48
|
if (lastCellPos === cell.pos && direction === TAB_FORWARD_DIRECTION) {
|
|
49
49
|
insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.KEYBOARD, {
|
|
50
50
|
index: map.height,
|
|
@@ -58,4 +58,94 @@ export var goToNextCell = function goToNextCell(editorAnalyticsAPI, ariaNotify,
|
|
|
58
58
|
return true;
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
|
-
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Moves the cursor vertically from a NodeSelection within a table cell.
|
|
65
|
+
* - If content exists above/below within the cell, lets ProseMirror handle it.
|
|
66
|
+
* - Otherwise, moves to the next cell (down to start, up to last line).
|
|
67
|
+
*/
|
|
68
|
+
export var goToNextCellVertical = function goToNextCellVertical(direction) {
|
|
69
|
+
return function (state, dispatch) {
|
|
70
|
+
var selection = state.selection;
|
|
71
|
+
var nestedTableSelection = isSelectionTableNestedInTable(state);
|
|
72
|
+
if (!(selection instanceof NodeSelection) && !nestedTableSelection) {
|
|
73
|
+
return false; // Let ProseMirror handle other selection types
|
|
74
|
+
}
|
|
75
|
+
var table = findTable(selection);
|
|
76
|
+
var cell = findCellClosestToPos(state.doc.resolve(selection.from));
|
|
77
|
+
var selectionPos = selection.from;
|
|
78
|
+
|
|
79
|
+
// Handle when we have nested table fully selected
|
|
80
|
+
if (table && nestedTableSelection && isTableSelected(selection)) {
|
|
81
|
+
var parentTablePos = table.pos;
|
|
82
|
+
table = findTableClosestToPos(state.doc.resolve(parentTablePos));
|
|
83
|
+
cell = findCellClosestToPos(state.doc.resolve(parentTablePos));
|
|
84
|
+
selectionPos = parentTablePos;
|
|
85
|
+
}
|
|
86
|
+
if (!table || !cell || !cell.pos) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
var _state$schema$nodes2 = state.schema.nodes,
|
|
90
|
+
tableCell = _state$schema$nodes2.tableCell,
|
|
91
|
+
tableHeader = _state$schema$nodes2.tableHeader;
|
|
92
|
+
|
|
93
|
+
// Let ProseMirror handle movement within the cell if content exists above/below
|
|
94
|
+
if (cellHasContentInDirection(cell.node, cell.pos, selectionPos, direction)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Move to the next cell vertically
|
|
99
|
+
var map = TableMap.get(table.node);
|
|
100
|
+
var nextCellPos = map.nextCell(cell.pos - table.start, 'vert', direction);
|
|
101
|
+
if (dispatch && nextCellPos) {
|
|
102
|
+
var _$nextCell$nodeAfter, _$nextCell$nodeAfter2;
|
|
103
|
+
var nextCellStart = table.start + nextCellPos;
|
|
104
|
+
var $nextCell = state.doc.resolve(nextCellStart);
|
|
105
|
+
if ((_$nextCell$nodeAfter = $nextCell.nodeAfter) !== null && _$nextCell$nodeAfter !== void 0 && _$nextCell$nodeAfter.type && [tableCell, tableHeader].includes((_$nextCell$nodeAfter2 = $nextCell.nodeAfter) === null || _$nextCell$nodeAfter2 === void 0 ? void 0 : _$nextCell$nodeAfter2.type)) {
|
|
106
|
+
var contentPos = getTargetPositionInNextCell($nextCell.nodeAfter, nextCellStart, direction);
|
|
107
|
+
dispatch(state.tr.setSelection(TextSelection.create(state.doc, contentPos)));
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return false; // No next cell found
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
function cellHasContentInDirection(cellNode, cellPos, selectionPos, direction) {
|
|
116
|
+
var hasContent = false;
|
|
117
|
+
cellNode.content.forEach(function (node, offset) {
|
|
118
|
+
var nodeStart = cellPos + 1 + offset;
|
|
119
|
+
var nodeEnd = nodeStart + node.nodeSize;
|
|
120
|
+
if (direction === 1 && nodeStart > selectionPos && node.isBlock) {
|
|
121
|
+
hasContent = true; // Content below
|
|
122
|
+
} else if (direction === -1 && nodeEnd <= selectionPos && node.isBlock) {
|
|
123
|
+
hasContent = true; // Content above
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
return hasContent;
|
|
127
|
+
}
|
|
128
|
+
function getTargetPositionInNextCell(cellNode, nextCellStart, direction) {
|
|
129
|
+
var contentPos = nextCellStart + 1; // Default: just inside the cell
|
|
130
|
+
if (cellNode.content.size > 0) {
|
|
131
|
+
if (direction === 1) {
|
|
132
|
+
var firstChild = cellNode.firstChild;
|
|
133
|
+
if (firstChild && firstChild.isBlock) {
|
|
134
|
+
contentPos = nextCellStart + 1 + (firstChild.isLeaf ? 0 : 1); // Down: Start of first block
|
|
135
|
+
}
|
|
136
|
+
} else if (direction === -1) {
|
|
137
|
+
var lastBlock;
|
|
138
|
+
var lastOffset = 0;
|
|
139
|
+
cellNode.content.forEach(function (node, offset) {
|
|
140
|
+
if (node.isBlock) {
|
|
141
|
+
lastBlock = node;
|
|
142
|
+
lastOffset = offset;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
if (lastBlock) {
|
|
146
|
+
contentPos = nextCellStart + 1 + lastOffset + (lastBlock.isLeaf ? 0 : lastBlock.nodeSize - 1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return contentPos;
|
|
151
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
-
import { addColumnAfter, addColumnAfterVO, addColumnBefore, addColumnBeforeVO, addRowAfter, addRowAfterVO, addRowBefore, addRowBeforeVO, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, escape, focusToContextMenuTrigger, increaseMediaSize, moveColumnLeft, moveColumnRight, moveLeft, moveRight, moveRowDown, moveRowUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
|
|
2
|
+
import { addColumnAfter, addColumnAfterVO, addColumnBefore, addColumnBeforeVO, addRowAfter, addRowAfterVO, addRowBefore, addRowBeforeVO, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, escape, focusToContextMenuTrigger, increaseMediaSize, moveColumnLeft, moveColumnRight, moveDown, moveLeft, moveRight, moveRowDown, moveRowUp, moveUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
|
|
3
3
|
import { editorCommandToPMCommand } from '@atlaskit/editor-common/preset';
|
|
4
4
|
import { chainCommands } from '@atlaskit/editor-prosemirror/commands';
|
|
5
5
|
import { keymap } from '@atlaskit/editor-prosemirror/keymap';
|
|
@@ -8,6 +8,7 @@ import { moveSourceWithAnalyticsViaShortcut } from '../pm-plugins/drag-and-drop/
|
|
|
8
8
|
import { goToNextCell, moveCursorBackward, setFocusToCellMenu } from './commands';
|
|
9
9
|
import { activateNextResizeArea, initiateKeyboardColumnResizing, stopKeyboardColumnResizing } from './commands/column-resize';
|
|
10
10
|
import { addRowAroundSelection, changeColumnWidthByStepWithAnalytics, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut, deleteTableIfSelectedWithAnalytics, emptyMultipleCellsWithAnalytics } from './commands/commands-with-analytics';
|
|
11
|
+
import { goToNextCellVertical } from './commands/go-to-next-cell';
|
|
11
12
|
import { addColumnAfter as addColumnAfterCommand, addColumnBefore as addColumnBeforeCommand, createTable, insertTableWithNestingSupport } from './commands/insert';
|
|
12
13
|
export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProviderAPI, editorAnalyticsAPI, dragAndDropEnabled) {
|
|
13
14
|
var _pluginInjectionApi$a;
|
|
@@ -156,6 +157,14 @@ export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProvide
|
|
|
156
157
|
bindKeymapWithCommand(
|
|
157
158
|
// Ignored via go/ees005
|
|
158
159
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
160
|
+
moveDown.common, goToNextCellVertical(1), list);
|
|
161
|
+
bindKeymapWithCommand(
|
|
162
|
+
// Ignored via go/ees005
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
164
|
+
moveUp.common, goToNextCellVertical(-1), list);
|
|
165
|
+
bindKeymapWithCommand(
|
|
166
|
+
// Ignored via go/ees005
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
159
168
|
decreaseMediaSize.common, changeColumnWidthByStepWithAnalytics(editorAnalyticsAPI, api)(-10, getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, !!isCommentEditor, INPUT_METHOD.SHORTCUT, ariaNotifyPlugin, getIntl), list);
|
|
160
169
|
bindKeymapWithCommand(
|
|
161
170
|
// Ignored via go/ees005
|
|
@@ -3,3 +3,9 @@ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
|
3
3
|
import type { Command } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { Direction } from '@atlaskit/editor-tables/types';
|
|
5
5
|
export declare const goToNextCell: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, ariaNotify?: ((message: string) => void) | undefined, getIntl?: () => IntlShape) => (direction: Direction) => Command;
|
|
6
|
+
/**
|
|
7
|
+
* Moves the cursor vertically from a NodeSelection within a table cell.
|
|
8
|
+
* - If content exists above/below within the cell, lets ProseMirror handle it.
|
|
9
|
+
* - Otherwise, moves to the next cell (down to start, up to last line).
|
|
10
|
+
*/
|
|
11
|
+
export declare const goToNextCellVertical: (direction: Direction) => Command;
|
|
@@ -3,3 +3,9 @@ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
|
3
3
|
import type { Command } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { Direction } from '@atlaskit/editor-tables/types';
|
|
5
5
|
export declare const goToNextCell: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, ariaNotify?: ((message: string) => void) | undefined, getIntl?: () => IntlShape) => (direction: Direction) => Command;
|
|
6
|
+
/**
|
|
7
|
+
* Moves the cursor vertically from a NodeSelection within a table cell.
|
|
8
|
+
* - If content exists above/below within the cell, lets ProseMirror handle it.
|
|
9
|
+
* - Otherwise, moves to the next cell (down to start, up to last line).
|
|
10
|
+
*/
|
|
11
|
+
export declare const goToNextCellVertical: (direction: Direction) => Command;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-table",
|
|
3
|
-
"version": "10.4.
|
|
3
|
+
"version": "10.4.7",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@atlaskit/editor-plugin-batch-attribute-updates": "^2.1.0",
|
|
40
40
|
"@atlaskit/editor-plugin-content-insertion": "^2.1.0",
|
|
41
41
|
"@atlaskit/editor-plugin-editor-viewmode": "^3.0.0",
|
|
42
|
-
"@atlaskit/editor-plugin-extension": "
|
|
42
|
+
"@atlaskit/editor-plugin-extension": "5.0.8",
|
|
43
43
|
"@atlaskit/editor-plugin-guideline": "^2.0.0",
|
|
44
44
|
"@atlaskit/editor-plugin-selection": "^2.1.0",
|
|
45
45
|
"@atlaskit/editor-plugin-width": "^3.0.0",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@atlaskit/pragmatic-drag-and-drop": "^1.5.0",
|
|
53
53
|
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
|
|
54
54
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.0",
|
|
55
|
-
"@atlaskit/primitives": "^14.
|
|
55
|
+
"@atlaskit/primitives": "^14.2.0",
|
|
56
56
|
"@atlaskit/theme": "^18.0.0",
|
|
57
57
|
"@atlaskit/tmp-editor-statsig": "^4.1.0",
|
|
58
58
|
"@atlaskit/toggle": "^15.0.0",
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
// #region Constants
|
|
2
1
|
import type { IntlShape } from 'react-intl-next/src/types';
|
|
3
2
|
|
|
4
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
5
4
|
import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
5
|
+
import { isSelectionTableNestedInTable } from '@atlaskit/editor-common/nesting';
|
|
6
6
|
import type { Command } from '@atlaskit/editor-common/types';
|
|
7
|
+
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
+
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
7
9
|
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
8
10
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
9
11
|
import type { Direction } from '@atlaskit/editor-tables/types';
|
|
10
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
goToNextCell as baseGotoNextCell,
|
|
14
|
+
findCellClosestToPos,
|
|
15
|
+
findTable,
|
|
16
|
+
findTableClosestToPos,
|
|
17
|
+
isTableSelected,
|
|
18
|
+
} from '@atlaskit/editor-tables/utils';
|
|
11
19
|
|
|
12
20
|
import { getPluginState } from '../plugin-factory';
|
|
13
21
|
|
|
@@ -47,7 +55,7 @@ export const goToNextCell =
|
|
|
47
55
|
const firstCellPos = map.positionAt(0, 0, table.node) + table.start;
|
|
48
56
|
const lastCellPos = map.positionAt(map.height - 1, map.width - 1, table.node) + table.start;
|
|
49
57
|
|
|
50
|
-
//
|
|
58
|
+
// When tabbing backwards at first cell (top left), insert row at the start of table
|
|
51
59
|
if (firstCellPos === cell.pos && direction === TAB_BACKWARD_DIRECTION) {
|
|
52
60
|
insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.KEYBOARD, {
|
|
53
61
|
index: 0,
|
|
@@ -56,7 +64,7 @@ export const goToNextCell =
|
|
|
56
64
|
return true;
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
//
|
|
67
|
+
// When tabbing forwards at last cell (bottom right), insert row at the end of table
|
|
60
68
|
if (lastCellPos === cell.pos && direction === TAB_FORWARD_DIRECTION) {
|
|
61
69
|
insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.KEYBOARD, {
|
|
62
70
|
index: map.height,
|
|
@@ -71,3 +79,120 @@ export const goToNextCell =
|
|
|
71
79
|
|
|
72
80
|
return true;
|
|
73
81
|
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Moves the cursor vertically from a NodeSelection within a table cell.
|
|
85
|
+
* - If content exists above/below within the cell, lets ProseMirror handle it.
|
|
86
|
+
* - Otherwise, moves to the next cell (down to start, up to last line).
|
|
87
|
+
*/
|
|
88
|
+
export const goToNextCellVertical =
|
|
89
|
+
(direction: Direction): Command =>
|
|
90
|
+
(state, dispatch) => {
|
|
91
|
+
const { selection } = state;
|
|
92
|
+
const nestedTableSelection = isSelectionTableNestedInTable(state);
|
|
93
|
+
|
|
94
|
+
if (!(selection instanceof NodeSelection) && !nestedTableSelection) {
|
|
95
|
+
return false; // Let ProseMirror handle other selection types
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let table = findTable(selection);
|
|
99
|
+
let cell = findCellClosestToPos(state.doc.resolve(selection.from));
|
|
100
|
+
let selectionPos = selection.from;
|
|
101
|
+
|
|
102
|
+
// Handle when we have nested table fully selected
|
|
103
|
+
if (table && nestedTableSelection && isTableSelected(selection)) {
|
|
104
|
+
const parentTablePos = table.pos;
|
|
105
|
+
table = findTableClosestToPos(state.doc.resolve(parentTablePos));
|
|
106
|
+
cell = findCellClosestToPos(state.doc.resolve(parentTablePos));
|
|
107
|
+
selectionPos = parentTablePos;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!table || !cell || !cell.pos) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const { tableCell, tableHeader } = state.schema.nodes;
|
|
115
|
+
|
|
116
|
+
// Let ProseMirror handle movement within the cell if content exists above/below
|
|
117
|
+
if (cellHasContentInDirection(cell.node, cell.pos, selectionPos, direction)) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Move to the next cell vertically
|
|
122
|
+
const map = TableMap.get(table.node);
|
|
123
|
+
const nextCellPos = map.nextCell(cell.pos - table.start, 'vert', direction);
|
|
124
|
+
if (dispatch && nextCellPos) {
|
|
125
|
+
const nextCellStart = table.start + nextCellPos;
|
|
126
|
+
const $nextCell = state.doc.resolve(nextCellStart);
|
|
127
|
+
|
|
128
|
+
if (
|
|
129
|
+
$nextCell.nodeAfter?.type &&
|
|
130
|
+
[tableCell, tableHeader].includes($nextCell.nodeAfter?.type)
|
|
131
|
+
) {
|
|
132
|
+
const contentPos = getTargetPositionInNextCell(
|
|
133
|
+
$nextCell.nodeAfter,
|
|
134
|
+
nextCellStart,
|
|
135
|
+
direction,
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
dispatch(state.tr.setSelection(TextSelection.create(state.doc, contentPos)));
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return false; // No next cell found
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
function cellHasContentInDirection(
|
|
149
|
+
cellNode: PMNode,
|
|
150
|
+
cellPos: number,
|
|
151
|
+
selectionPos: number,
|
|
152
|
+
direction: Direction,
|
|
153
|
+
): boolean {
|
|
154
|
+
let hasContent = false;
|
|
155
|
+
|
|
156
|
+
cellNode.content.forEach((node: PMNode, offset: number) => {
|
|
157
|
+
const nodeStart = cellPos + 1 + offset;
|
|
158
|
+
const nodeEnd = nodeStart + node.nodeSize;
|
|
159
|
+
|
|
160
|
+
if (direction === 1 && nodeStart > selectionPos && node.isBlock) {
|
|
161
|
+
hasContent = true; // Content below
|
|
162
|
+
} else if (direction === -1 && nodeEnd <= selectionPos && node.isBlock) {
|
|
163
|
+
hasContent = true; // Content above
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return hasContent;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function getTargetPositionInNextCell(
|
|
171
|
+
cellNode: PMNode,
|
|
172
|
+
nextCellStart: number,
|
|
173
|
+
direction: Direction,
|
|
174
|
+
): number {
|
|
175
|
+
let contentPos = nextCellStart + 1; // Default: just inside the cell
|
|
176
|
+
if (cellNode.content.size > 0) {
|
|
177
|
+
if (direction === 1) {
|
|
178
|
+
const firstChild = cellNode.firstChild;
|
|
179
|
+
if (firstChild && firstChild.isBlock) {
|
|
180
|
+
contentPos = nextCellStart + 1 + (firstChild.isLeaf ? 0 : 1); // Down: Start of first block
|
|
181
|
+
}
|
|
182
|
+
} else if (direction === -1) {
|
|
183
|
+
let lastBlock: PMNode | undefined;
|
|
184
|
+
let lastOffset = 0;
|
|
185
|
+
cellNode.content.forEach((node: PMNode, offset: number) => {
|
|
186
|
+
if (node.isBlock) {
|
|
187
|
+
lastBlock = node;
|
|
188
|
+
lastOffset = offset;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
if (lastBlock) {
|
|
192
|
+
contentPos =
|
|
193
|
+
nextCellStart + 1 + lastOffset + (lastBlock.isLeaf ? 0 : lastBlock.nodeSize - 1);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return contentPos;
|
|
198
|
+
}
|
package/src/pm-plugins/keymap.ts
CHANGED
|
@@ -27,10 +27,12 @@ import {
|
|
|
27
27
|
increaseMediaSize,
|
|
28
28
|
moveColumnLeft,
|
|
29
29
|
moveColumnRight,
|
|
30
|
+
moveDown,
|
|
30
31
|
moveLeft,
|
|
31
32
|
moveRight,
|
|
32
33
|
moveRowDown,
|
|
33
34
|
moveRowUp,
|
|
35
|
+
moveUp,
|
|
34
36
|
nextCell,
|
|
35
37
|
previousCell,
|
|
36
38
|
startColumnResizing,
|
|
@@ -60,6 +62,7 @@ import {
|
|
|
60
62
|
deleteTableIfSelectedWithAnalytics,
|
|
61
63
|
emptyMultipleCellsWithAnalytics,
|
|
62
64
|
} from './commands/commands-with-analytics';
|
|
65
|
+
import { goToNextCellVertical } from './commands/go-to-next-cell';
|
|
63
66
|
import {
|
|
64
67
|
addColumnAfter as addColumnAfterCommand,
|
|
65
68
|
addColumnBefore as addColumnBeforeCommand,
|
|
@@ -362,6 +365,22 @@ export function keymapPlugin(
|
|
|
362
365
|
list,
|
|
363
366
|
);
|
|
364
367
|
|
|
368
|
+
bindKeymapWithCommand(
|
|
369
|
+
// Ignored via go/ees005
|
|
370
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
371
|
+
moveDown.common!,
|
|
372
|
+
goToNextCellVertical(1),
|
|
373
|
+
list,
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
bindKeymapWithCommand(
|
|
377
|
+
// Ignored via go/ees005
|
|
378
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
379
|
+
moveUp.common!,
|
|
380
|
+
goToNextCellVertical(-1),
|
|
381
|
+
list,
|
|
382
|
+
);
|
|
383
|
+
|
|
365
384
|
bindKeymapWithCommand(
|
|
366
385
|
// Ignored via go/ees005
|
|
367
386
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|