@atlaskit/editor-plugin-table 10.4.4 → 10.4.6
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 +18 -0
- package/afm-cc/tsconfig.json +3 -0
- package/afm-jira/tsconfig.json +3 -0
- package/afm-post-office/tsconfig.json +3 -0
- package/dist/cjs/nodeviews/TableRow.js +1 -1
- package/dist/cjs/pm-plugins/commands/go-to-next-cell.js +96 -6
- package/dist/cjs/pm-plugins/keymap.js +9 -0
- package/dist/cjs/ui/toolbar.js +54 -7
- package/dist/es2019/nodeviews/TableRow.js +1 -1
- package/dist/es2019/pm-plugins/commands/go-to-next-cell.js +97 -6
- package/dist/es2019/pm-plugins/keymap.js +10 -1
- package/dist/es2019/ui/toolbar.js +54 -7
- package/dist/esm/nodeviews/TableRow.js +1 -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/esm/ui/toolbar.js +54 -7
- package/dist/types/pm-plugins/commands/go-to-next-cell.d.ts +6 -0
- package/dist/types/tablePluginType.d.ts +3 -1
- package/dist/types-ts4.5/pm-plugins/commands/go-to-next-cell.d.ts +6 -0
- package/dist/types-ts4.5/tablePluginType.d.ts +3 -1
- package/package.json +4 -6
- package/src/nodeviews/TableRow.ts +1 -2
- package/src/nodeviews/TableStickyScrollbar.ts +2 -3
- package/src/pm-plugins/commands/go-to-next-cell.ts +129 -4
- package/src/pm-plugins/keymap.ts +19 -0
- package/src/tablePluginType.ts +2 -0
- package/src/ui/toolbar.tsx +76 -12
- package/tsconfig.app.json +3 -0
|
@@ -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
|
package/dist/esm/ui/toolbar.js
CHANGED
|
@@ -11,8 +11,10 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
11
11
|
import { jsx } from '@emotion/react';
|
|
12
12
|
import { TableSortOrder as SortOrder } from '@atlaskit/custom-steps';
|
|
13
13
|
import { CHANGE_ALIGNMENT_REASON, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
14
|
+
import { DropdownMenuExtensionItems } from '@atlaskit/editor-common/floating-toolbar';
|
|
14
15
|
import { addColumnAfter, addRowAfter, backspace, tooltip } from '@atlaskit/editor-common/keymaps';
|
|
15
16
|
import commonMessages, { tableMessages as messages } from '@atlaskit/editor-common/messages';
|
|
17
|
+
import { isSelectionTableNestedInTable } from '@atlaskit/editor-common/nesting';
|
|
16
18
|
import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
|
|
17
19
|
import { cellBackgroundColorPalette, DEFAULT_BORDER_COLOR } from '@atlaskit/editor-common/ui-color';
|
|
18
20
|
import { closestElement, getChildrenInfo as _getChildrenInfo, getNodeName, isReferencedSource } from '@atlaskit/editor-common/utils';
|
|
@@ -23,6 +25,7 @@ import { Rect, TableMap } from '@atlaskit/editor-tables/table-map';
|
|
|
23
25
|
import { findCellRectClosestToPos, findTable, getSelectionRect, isSelectionType, splitCell } from '@atlaskit/editor-tables/utils';
|
|
24
26
|
import AlignImageCenterIcon from '@atlaskit/icon/core/align-image-center';
|
|
25
27
|
import AlignImageLeftIcon from '@atlaskit/icon/core/align-image-left';
|
|
28
|
+
import CopyIcon from '@atlaskit/icon/core/copy';
|
|
26
29
|
import CustomizeIcon from '@atlaskit/icon/core/customize';
|
|
27
30
|
import DeleteIcon from '@atlaskit/icon/core/delete';
|
|
28
31
|
import TableColumnsDistributeIcon from '@atlaskit/icon/core/table-columns-distribute';
|
|
@@ -446,6 +449,7 @@ export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth,
|
|
|
446
449
|
onBlur: clearHoverSelection()
|
|
447
450
|
}]
|
|
448
451
|
};
|
|
452
|
+
var isNestedTable = fg('platform_editor_use_nested_table_pm_nodes') && isSelectionTableNestedInTable(state);
|
|
449
453
|
return {
|
|
450
454
|
title: 'Table floating controls',
|
|
451
455
|
getDomRef: getDomRef,
|
|
@@ -456,16 +460,59 @@ export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth,
|
|
|
456
460
|
},
|
|
457
461
|
zIndex: akEditorFloatingPanelZIndex + 1,
|
|
458
462
|
// Place the context menu slightly above the others
|
|
459
|
-
items: [menu, separator(menu.hidden)].concat(_toConsumableArray(alignmentMenu), [separator(alignmentMenu.length === 0)], _toConsumableArray(cellItems), _toConsumableArray(columnSettingsItems), _toConsumableArray(colorPicker), [
|
|
460
|
-
// TODO: ED-26961 - editor controls to move to overflow menu
|
|
461
|
-
{
|
|
463
|
+
items: [menu, separator(menu.hidden)].concat(_toConsumableArray(alignmentMenu), [separator(alignmentMenu.length === 0)], _toConsumableArray(cellItems), _toConsumableArray(columnSettingsItems), _toConsumableArray(colorPicker), _toConsumableArray(editorExperiment('platform_editor_controls', 'control') ? [{
|
|
462
464
|
type: 'extensions-placeholder',
|
|
463
465
|
separator: 'end'
|
|
464
|
-
}
|
|
466
|
+
}, copyButton, {
|
|
465
467
|
type: 'separator'
|
|
466
|
-
}, deleteButton] : [
|
|
467
|
-
type: '
|
|
468
|
-
|
|
468
|
+
}, deleteButton] : [{
|
|
469
|
+
type: 'overflow-dropdown',
|
|
470
|
+
dropdownWidth: 220,
|
|
471
|
+
options: [{
|
|
472
|
+
type: 'custom',
|
|
473
|
+
fallback: [],
|
|
474
|
+
render: function render(editorView, dropdownOptions) {
|
|
475
|
+
var _api$extension, _api$extension2, _api$extension3;
|
|
476
|
+
if (!editorView) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
var extensionState = api === null || api === void 0 || (_api$extension = api.extension) === null || _api$extension === void 0 || (_api$extension = _api$extension.sharedState) === null || _api$extension === void 0 ? void 0 : _api$extension.currentState();
|
|
480
|
+
var extensionApi = api === null || api === void 0 || (_api$extension2 = api.extension) === null || _api$extension2 === void 0 ? void 0 : _api$extension2.actions.api();
|
|
481
|
+
if (!extensionApi || !(extensionState !== null && extensionState !== void 0 && extensionState.extensionProvider)) {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
return jsx(DropdownMenuExtensionItems, {
|
|
485
|
+
node: tableObject.node,
|
|
486
|
+
editorView: editorView,
|
|
487
|
+
extension: {
|
|
488
|
+
extensionProvider: extensionState !== null && extensionState !== void 0 && extensionState.extensionProvider ? Promise.resolve(extensionState.extensionProvider) : undefined,
|
|
489
|
+
extensionApi: api === null || api === void 0 || (_api$extension3 = api.extension) === null || _api$extension3 === void 0 ? void 0 : _api$extension3.actions.api()
|
|
490
|
+
},
|
|
491
|
+
dropdownOptions: dropdownOptions,
|
|
492
|
+
disabled: function disabled(key) {
|
|
493
|
+
return isNestedTable && ['referentiality:connections', 'chart:insert-chart'].includes(key);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
}, {
|
|
498
|
+
title: intl.formatMessage(commonMessages.copyToClipboard),
|
|
499
|
+
onClick: function onClick() {
|
|
500
|
+
var _api$core, _api$floatingToolbar;
|
|
501
|
+
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute( // @ts-ignore
|
|
502
|
+
api === null || api === void 0 || (_api$floatingToolbar = api.floatingToolbar) === null || _api$floatingToolbar === void 0 ? void 0 : _api$floatingToolbar.commands.copyNode(nodeType));
|
|
503
|
+
return true;
|
|
504
|
+
},
|
|
505
|
+
icon: jsx(CopyIcon, {
|
|
506
|
+
label: intl.formatMessage(commonMessages.copyToClipboard)
|
|
507
|
+
})
|
|
508
|
+
}, {
|
|
509
|
+
title: intl.formatMessage(commonMessages.delete),
|
|
510
|
+
onClick: deleteTableWithAnalytics(editorAnalyticsAPI),
|
|
511
|
+
icon: jsx(DeleteIcon, {
|
|
512
|
+
label: intl.formatMessage(commonMessages.delete)
|
|
513
|
+
})
|
|
514
|
+
}]
|
|
515
|
+
}])),
|
|
469
516
|
scrollable: true
|
|
470
517
|
};
|
|
471
518
|
}
|
|
@@ -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;
|
|
@@ -5,6 +5,7 @@ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
|
5
5
|
import type { BatchAttributeUpdatesPlugin } from '@atlaskit/editor-plugin-batch-attribute-updates';
|
|
6
6
|
import type { ContentInsertionPlugin } from '@atlaskit/editor-plugin-content-insertion';
|
|
7
7
|
import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
|
|
8
|
+
import type { ExtensionPlugin } from '@atlaskit/editor-plugin-extension';
|
|
8
9
|
import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
|
|
9
10
|
import type { GuidelinePlugin } from '@atlaskit/editor-plugin-guideline';
|
|
10
11
|
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
@@ -45,7 +46,8 @@ export type TablePluginDependencies = [
|
|
|
45
46
|
OptionalPlugin<AccessibilityUtilsPlugin>,
|
|
46
47
|
OptionalPlugin<MediaPlugin>,
|
|
47
48
|
OptionalPlugin<EditorViewModePlugin>,
|
|
48
|
-
OptionalPlugin<FeatureFlagsPlugin
|
|
49
|
+
OptionalPlugin<FeatureFlagsPlugin>,
|
|
50
|
+
OptionalPlugin<ExtensionPlugin>
|
|
49
51
|
];
|
|
50
52
|
export type TablePlugin = NextEditorPlugin<'table', {
|
|
51
53
|
pluginConfiguration: TablePluginOptions | undefined;
|
|
@@ -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;
|
|
@@ -5,6 +5,7 @@ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
|
5
5
|
import type { BatchAttributeUpdatesPlugin } from '@atlaskit/editor-plugin-batch-attribute-updates';
|
|
6
6
|
import type { ContentInsertionPlugin } from '@atlaskit/editor-plugin-content-insertion';
|
|
7
7
|
import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
|
|
8
|
+
import type { ExtensionPlugin } from '@atlaskit/editor-plugin-extension';
|
|
8
9
|
import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
|
|
9
10
|
import type { GuidelinePlugin } from '@atlaskit/editor-plugin-guideline';
|
|
10
11
|
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
@@ -45,7 +46,8 @@ export type TablePluginDependencies = [
|
|
|
45
46
|
OptionalPlugin<AccessibilityUtilsPlugin>,
|
|
46
47
|
OptionalPlugin<MediaPlugin>,
|
|
47
48
|
OptionalPlugin<EditorViewModePlugin>,
|
|
48
|
-
OptionalPlugin<FeatureFlagsPlugin
|
|
49
|
+
OptionalPlugin<FeatureFlagsPlugin>,
|
|
50
|
+
OptionalPlugin<ExtensionPlugin>
|
|
49
51
|
];
|
|
50
52
|
export type TablePlugin = NextEditorPlugin<'table', {
|
|
51
53
|
pluginConfiguration: TablePluginOptions | undefined;
|
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.6",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -32,13 +32,14 @@
|
|
|
32
32
|
"@atlaskit/adf-schema": "^47.6.0",
|
|
33
33
|
"@atlaskit/button": "^21.1.0",
|
|
34
34
|
"@atlaskit/custom-steps": "^0.11.0",
|
|
35
|
-
"@atlaskit/editor-common": "^102.
|
|
35
|
+
"@atlaskit/editor-common": "^102.11.0",
|
|
36
36
|
"@atlaskit/editor-palette": "^2.1.0",
|
|
37
37
|
"@atlaskit/editor-plugin-accessibility-utils": "^2.0.0",
|
|
38
38
|
"@atlaskit/editor-plugin-analytics": "^2.2.0",
|
|
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": "5.0.7",
|
|
42
43
|
"@atlaskit/editor-plugin-guideline": "^2.0.0",
|
|
43
44
|
"@atlaskit/editor-plugin-selection": "^2.1.0",
|
|
44
45
|
"@atlaskit/editor-plugin-width": "^3.0.0",
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
"@atlaskit/pragmatic-drag-and-drop": "^1.5.0",
|
|
52
53
|
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
|
|
53
54
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.0",
|
|
54
|
-
"@atlaskit/primitives": "^14.
|
|
55
|
+
"@atlaskit/primitives": "^14.2.0",
|
|
55
56
|
"@atlaskit/theme": "^18.0.0",
|
|
56
57
|
"@atlaskit/tmp-editor-statsig": "^4.1.0",
|
|
57
58
|
"@atlaskit/toggle": "^15.0.0",
|
|
@@ -152,9 +153,6 @@
|
|
|
152
153
|
"platform_editor_nested_tables_paste_wrap_fix": {
|
|
153
154
|
"type": "boolean"
|
|
154
155
|
},
|
|
155
|
-
"platform_editor_advanced_layouts_post_fix_patch_4": {
|
|
156
|
-
"type": "boolean"
|
|
157
|
-
},
|
|
158
156
|
"nested_table_control_padding_with_css": {
|
|
159
157
|
"type": "boolean"
|
|
160
158
|
},
|
|
@@ -454,8 +454,7 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
454
454
|
if (
|
|
455
455
|
// is Safari
|
|
456
456
|
navigator.userAgent.includes('AppleWebKit') &&
|
|
457
|
-
!navigator.userAgent.includes('Chrome')
|
|
458
|
-
fg('platform_editor_advanced_layouts_post_fix_patch_4')
|
|
457
|
+
!navigator.userAgent.includes('Chrome')
|
|
459
458
|
) {
|
|
460
459
|
const pos = this.getPos();
|
|
461
460
|
if (typeof pos === 'number') {
|
|
@@ -150,8 +150,8 @@ export class TableStickyScrollbar {
|
|
|
150
150
|
// so the boundingClientRect.top will never be less than the rootBounds.top,
|
|
151
151
|
// so we need to check if the boundingClientRect.top is less than 20% of the rootBounds.height
|
|
152
152
|
// to determine if the bottom sentinel is above the scroll area
|
|
153
|
-
(entry.boundingClientRect.top < (
|
|
154
|
-
|
|
153
|
+
(entry.boundingClientRect.top < (entry.rootBounds?.height || 0) * 0.2 &&
|
|
154
|
+
fg('platform_editor_scroll_table_flickering_fix'));
|
|
155
155
|
|
|
156
156
|
this.bottomSentinelState = sentinelIsAboveScrollArea
|
|
157
157
|
? 'above'
|
|
@@ -166,7 +166,6 @@ export class TableStickyScrollbar {
|
|
|
166
166
|
const sentinelIsBelowScrollArea =
|
|
167
167
|
(entry.rootBounds?.bottom || 0) < entry.boundingClientRect.top;
|
|
168
168
|
|
|
169
|
-
|
|
170
169
|
this.topSentinelState = sentinelIsBelowScrollArea
|
|
171
170
|
? 'below'
|
|
172
171
|
: entry.isIntersecting
|
|
@@ -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
|
package/src/tablePluginType.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
|
11
11
|
import type { BatchAttributeUpdatesPlugin } from '@atlaskit/editor-plugin-batch-attribute-updates';
|
|
12
12
|
import type { ContentInsertionPlugin } from '@atlaskit/editor-plugin-content-insertion';
|
|
13
13
|
import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
|
|
14
|
+
import type { ExtensionPlugin } from '@atlaskit/editor-plugin-extension';
|
|
14
15
|
import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
|
|
15
16
|
import type { GuidelinePlugin } from '@atlaskit/editor-plugin-guideline';
|
|
16
17
|
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
@@ -80,6 +81,7 @@ export type TablePluginDependencies = [
|
|
|
80
81
|
OptionalPlugin<MediaPlugin>,
|
|
81
82
|
OptionalPlugin<EditorViewModePlugin>,
|
|
82
83
|
OptionalPlugin<FeatureFlagsPlugin>,
|
|
84
|
+
OptionalPlugin<ExtensionPlugin>,
|
|
83
85
|
];
|
|
84
86
|
|
|
85
87
|
export type TablePlugin = NextEditorPlugin<
|