@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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 10.4.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#124950](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/124950)
8
+ [`45961c4f4a9a3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/45961c4f4a9a3) -
9
+ [ux] ED-25485 Fixes issue where up/down arrow keys would move to the wrong cell in a table if
10
+ there was a node selection inside the table.
11
+
12
+ ## 10.4.5
13
+
14
+ ### Patch Changes
15
+
16
+ - [#127253](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/127253)
17
+ [`a2593d5c73ccb`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a2593d5c73ccb) -
18
+ [ux] Table overflow menu on floating toolbar
19
+ - Updated dependencies
20
+
3
21
  ## 10.4.4
4
22
 
5
23
  ### Patch Changes
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-plugin-editor-viewmode/afm-cc/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../editor-plugin-extension/afm-cc/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../editor-plugin-guideline/afm-cc/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-plugin-editor-viewmode/afm-jira/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../editor-plugin-extension/afm-jira/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../editor-plugin-guideline/afm-jira/tsconfig.json"
49
52
  },
@@ -44,6 +44,9 @@
44
44
  {
45
45
  "path": "../../editor-plugin-editor-viewmode/afm-post-office/tsconfig.json"
46
46
  },
47
+ {
48
+ "path": "../../editor-plugin-extension/afm-post-office/tsconfig.json"
49
+ },
47
50
  {
48
51
  "path": "../../editor-plugin-guideline/afm-post-office/tsconfig.json"
49
52
  },
@@ -414,7 +414,7 @@ var TableRow = exports.default = /*#__PURE__*/function (_TableNodeView) {
414
414
  value: function shouldSticky() {
415
415
  if (
416
416
  // is Safari
417
- navigator.userAgent.includes('AppleWebKit') && !navigator.userAgent.includes('Chrome') && (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_post_fix_patch_4')) {
417
+ navigator.userAgent.includes('AppleWebKit') && !navigator.userAgent.includes('Chrome')) {
418
418
  var pos = this.getPos();
419
419
  if (typeof pos === 'number') {
420
420
  var $tableRowPos = this.view.state.doc.resolve(pos);
@@ -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
- // when tabbing backwards at first cell (top left), insert row at the start of table
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
- // when tabbing forwards at last cell (bottom right), insert row at the end of table
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
@@ -12,8 +12,10 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
12
12
  var _react = require("@emotion/react");
13
13
  var _customSteps = require("@atlaskit/custom-steps");
14
14
  var _analytics = require("@atlaskit/editor-common/analytics");
15
+ var _floatingToolbar = require("@atlaskit/editor-common/floating-toolbar");
15
16
  var _keymaps = require("@atlaskit/editor-common/keymaps");
16
17
  var _messages = _interopRequireWildcard(require("@atlaskit/editor-common/messages"));
18
+ var _nesting = require("@atlaskit/editor-common/nesting");
17
19
  var _nodeWidth = require("@atlaskit/editor-common/node-width");
18
20
  var _uiColor = require("@atlaskit/editor-common/ui-color");
19
21
  var _utils = require("@atlaskit/editor-common/utils");
@@ -24,6 +26,7 @@ var _tableMap = require("@atlaskit/editor-tables/table-map");
24
26
  var _utils3 = require("@atlaskit/editor-tables/utils");
25
27
  var _alignImageCenter = _interopRequireDefault(require("@atlaskit/icon/core/align-image-center"));
26
28
  var _alignImageLeft = _interopRequireDefault(require("@atlaskit/icon/core/align-image-left"));
29
+ var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy"));
27
30
  var _customize = _interopRequireDefault(require("@atlaskit/icon/core/customize"));
28
31
  var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete"));
29
32
  var _tableColumnsDistribute = _interopRequireDefault(require("@atlaskit/icon/core/table-columns-distribute"));
@@ -454,6 +457,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
454
457
  onBlur: (0, _commands.clearHoverSelection)()
455
458
  }]
456
459
  };
460
+ var isNestedTable = (0, _platformFeatureFlags.fg)('platform_editor_use_nested_table_pm_nodes') && (0, _nesting.isSelectionTableNestedInTable)(state);
457
461
  return {
458
462
  title: 'Table floating controls',
459
463
  getDomRef: getDomRef,
@@ -464,16 +468,59 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
464
468
  },
465
469
  zIndex: _editorSharedStyles.akEditorFloatingPanelZIndex + 1,
466
470
  // Place the context menu slightly above the others
467
- items: [menu, separator(menu.hidden)].concat((0, _toConsumableArray2.default)(alignmentMenu), [separator(alignmentMenu.length === 0)], (0, _toConsumableArray2.default)(cellItems), (0, _toConsumableArray2.default)(columnSettingsItems), (0, _toConsumableArray2.default)(colorPicker), [
468
- // TODO: ED-26961 - editor controls to move to overflow menu
469
- {
471
+ items: [menu, separator(menu.hidden)].concat((0, _toConsumableArray2.default)(alignmentMenu), [separator(alignmentMenu.length === 0)], (0, _toConsumableArray2.default)(cellItems), (0, _toConsumableArray2.default)(columnSettingsItems), (0, _toConsumableArray2.default)(colorPicker), (0, _toConsumableArray2.default)((0, _experiments.editorExperiment)('platform_editor_controls', 'control') ? [{
470
472
  type: 'extensions-placeholder',
471
473
  separator: 'end'
472
- }], (0, _toConsumableArray2.default)((0, _experiments.editorExperiment)('platform_editor_controls', 'control') ? [copyButton, {
474
+ }, copyButton, {
473
475
  type: 'separator'
474
- }, deleteButton] : [deleteButton, {
475
- type: 'separator'
476
- }, copyButton])),
476
+ }, deleteButton] : [{
477
+ type: 'overflow-dropdown',
478
+ dropdownWidth: 220,
479
+ options: [{
480
+ type: 'custom',
481
+ fallback: [],
482
+ render: function render(editorView, dropdownOptions) {
483
+ var _api$extension, _api$extension2, _api$extension3;
484
+ if (!editorView) {
485
+ return null;
486
+ }
487
+ 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();
488
+ var extensionApi = api === null || api === void 0 || (_api$extension2 = api.extension) === null || _api$extension2 === void 0 ? void 0 : _api$extension2.actions.api();
489
+ if (!extensionApi || !(extensionState !== null && extensionState !== void 0 && extensionState.extensionProvider)) {
490
+ return null;
491
+ }
492
+ return (0, _react.jsx)(_floatingToolbar.DropdownMenuExtensionItems, {
493
+ node: tableObject.node,
494
+ editorView: editorView,
495
+ extension: {
496
+ extensionProvider: extensionState !== null && extensionState !== void 0 && extensionState.extensionProvider ? Promise.resolve(extensionState.extensionProvider) : undefined,
497
+ extensionApi: api === null || api === void 0 || (_api$extension3 = api.extension) === null || _api$extension3 === void 0 ? void 0 : _api$extension3.actions.api()
498
+ },
499
+ dropdownOptions: dropdownOptions,
500
+ disabled: function disabled(key) {
501
+ return isNestedTable && ['referentiality:connections', 'chart:insert-chart'].includes(key);
502
+ }
503
+ });
504
+ }
505
+ }, {
506
+ title: intl.formatMessage(_messages.default.copyToClipboard),
507
+ onClick: function onClick() {
508
+ var _api$core, _api$floatingToolbar;
509
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute( // @ts-ignore
510
+ api === null || api === void 0 || (_api$floatingToolbar = api.floatingToolbar) === null || _api$floatingToolbar === void 0 ? void 0 : _api$floatingToolbar.commands.copyNode(nodeType));
511
+ return true;
512
+ },
513
+ icon: (0, _react.jsx)(_copy.default, {
514
+ label: intl.formatMessage(_messages.default.copyToClipboard)
515
+ })
516
+ }, {
517
+ title: intl.formatMessage(_messages.default.delete),
518
+ onClick: (0, _commandsWithAnalytics.deleteTableWithAnalytics)(editorAnalyticsAPI),
519
+ icon: (0, _react.jsx)(_delete.default, {
520
+ label: intl.formatMessage(_messages.default.delete)
521
+ })
522
+ }]
523
+ }])),
477
524
  scrollable: true
478
525
  };
479
526
  }
@@ -375,7 +375,7 @@ export default class TableRow extends TableNodeView {
375
375
  shouldSticky() {
376
376
  if (
377
377
  // is Safari
378
- navigator.userAgent.includes('AppleWebKit') && !navigator.userAgent.includes('Chrome') && fg('platform_editor_advanced_layouts_post_fix_patch_4')) {
378
+ navigator.userAgent.includes('AppleWebKit') && !navigator.userAgent.includes('Chrome')) {
379
379
  const pos = this.getPos();
380
380
  if (typeof pos === 'number') {
381
381
  const $tableRowPos = this.view.state.doc.resolve(pos);
@@ -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
- // when tabbing backwards at first cell (top left), insert row at the start of table
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
- // when tabbing forwards at last cell (bottom right), insert row at the end of table
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
@@ -7,8 +7,10 @@ import _extends from "@babel/runtime/helpers/extends";
7
7
  import { jsx } from '@emotion/react';
8
8
  import { TableSortOrder as SortOrder } from '@atlaskit/custom-steps';
9
9
  import { CHANGE_ALIGNMENT_REASON, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
10
+ import { DropdownMenuExtensionItems } from '@atlaskit/editor-common/floating-toolbar';
10
11
  import { addColumnAfter, addRowAfter, backspace, tooltip } from '@atlaskit/editor-common/keymaps';
11
12
  import commonMessages, { tableMessages as messages } from '@atlaskit/editor-common/messages';
13
+ import { isSelectionTableNestedInTable } from '@atlaskit/editor-common/nesting';
12
14
  import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
13
15
  import { cellBackgroundColorPalette, DEFAULT_BORDER_COLOR } from '@atlaskit/editor-common/ui-color';
14
16
  import { closestElement, getChildrenInfo, getNodeName, isReferencedSource } from '@atlaskit/editor-common/utils';
@@ -19,6 +21,7 @@ import { Rect, TableMap } from '@atlaskit/editor-tables/table-map';
19
21
  import { findCellRectClosestToPos, findTable, getSelectionRect, isSelectionType, splitCell } from '@atlaskit/editor-tables/utils';
20
22
  import AlignImageCenterIcon from '@atlaskit/icon/core/align-image-center';
21
23
  import AlignImageLeftIcon from '@atlaskit/icon/core/align-image-left';
24
+ import CopyIcon from '@atlaskit/icon/core/copy';
22
25
  import CustomizeIcon from '@atlaskit/icon/core/customize';
23
26
  import DeleteIcon from '@atlaskit/icon/core/delete';
24
27
  import TableColumnsDistributeIcon from '@atlaskit/icon/core/table-columns-distribute';
@@ -426,6 +429,7 @@ export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAP
426
429
  onBlur: clearHoverSelection()
427
430
  }]
428
431
  };
432
+ const isNestedTable = fg('platform_editor_use_nested_table_pm_nodes') && isSelectionTableNestedInTable(state);
429
433
  return {
430
434
  title: 'Table floating controls',
431
435
  getDomRef,
@@ -436,16 +440,59 @@ export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAP
436
440
  },
437
441
  zIndex: akEditorFloatingPanelZIndex + 1,
438
442
  // Place the context menu slightly above the others
439
- items: [menu, separator(menu.hidden), ...alignmentMenu, separator(alignmentMenu.length === 0), ...cellItems, ...columnSettingsItems, ...colorPicker,
440
- // TODO: ED-26961 - editor controls to move to overflow menu
441
- {
443
+ items: [menu, separator(menu.hidden), ...alignmentMenu, separator(alignmentMenu.length === 0), ...cellItems, ...columnSettingsItems, ...colorPicker, ...(editorExperiment('platform_editor_controls', 'control') ? [{
442
444
  type: 'extensions-placeholder',
443
445
  separator: 'end'
444
- }, ...(editorExperiment('platform_editor_controls', 'control') ? [copyButton, {
446
+ }, copyButton, {
445
447
  type: 'separator'
446
- }, deleteButton] : [deleteButton, {
447
- type: 'separator'
448
- }, copyButton])],
448
+ }, deleteButton] : [{
449
+ type: 'overflow-dropdown',
450
+ dropdownWidth: 220,
451
+ options: [{
452
+ type: 'custom',
453
+ fallback: [],
454
+ render: (editorView, dropdownOptions) => {
455
+ var _api$extension, _api$extension$shared, _api$extension2, _api$extension3;
456
+ if (!editorView) {
457
+ return null;
458
+ }
459
+ const extensionState = api === null || api === void 0 ? void 0 : (_api$extension = api.extension) === null || _api$extension === void 0 ? void 0 : (_api$extension$shared = _api$extension.sharedState) === null || _api$extension$shared === void 0 ? void 0 : _api$extension$shared.currentState();
460
+ const extensionApi = api === null || api === void 0 ? void 0 : (_api$extension2 = api.extension) === null || _api$extension2 === void 0 ? void 0 : _api$extension2.actions.api();
461
+ if (!extensionApi || !(extensionState !== null && extensionState !== void 0 && extensionState.extensionProvider)) {
462
+ return null;
463
+ }
464
+ return jsx(DropdownMenuExtensionItems, {
465
+ node: tableObject.node,
466
+ editorView: editorView,
467
+ extension: {
468
+ extensionProvider: extensionState !== null && extensionState !== void 0 && extensionState.extensionProvider ? Promise.resolve(extensionState.extensionProvider) : undefined,
469
+ extensionApi: api === null || api === void 0 ? void 0 : (_api$extension3 = api.extension) === null || _api$extension3 === void 0 ? void 0 : _api$extension3.actions.api()
470
+ },
471
+ dropdownOptions: dropdownOptions,
472
+ disabled: key => {
473
+ return isNestedTable && ['referentiality:connections', 'chart:insert-chart'].includes(key);
474
+ }
475
+ });
476
+ }
477
+ }, {
478
+ title: intl.formatMessage(commonMessages.copyToClipboard),
479
+ onClick: () => {
480
+ var _api$core, _api$floatingToolbar;
481
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute( // @ts-ignore
482
+ api === null || api === void 0 ? void 0 : (_api$floatingToolbar = api.floatingToolbar) === null || _api$floatingToolbar === void 0 ? void 0 : _api$floatingToolbar.commands.copyNode(nodeType));
483
+ return true;
484
+ },
485
+ icon: jsx(CopyIcon, {
486
+ label: intl.formatMessage(commonMessages.copyToClipboard)
487
+ })
488
+ }, {
489
+ title: intl.formatMessage(commonMessages.delete),
490
+ onClick: deleteTableWithAnalytics(editorAnalyticsAPI),
491
+ icon: jsx(DeleteIcon, {
492
+ label: intl.formatMessage(commonMessages.delete)
493
+ })
494
+ }]
495
+ }])],
449
496
  scrollable: true
450
497
  };
451
498
  }
@@ -407,7 +407,7 @@ var TableRow = /*#__PURE__*/function (_TableNodeView) {
407
407
  value: function shouldSticky() {
408
408
  if (
409
409
  // is Safari
410
- navigator.userAgent.includes('AppleWebKit') && !navigator.userAgent.includes('Chrome') && fg('platform_editor_advanced_layouts_post_fix_patch_4')) {
410
+ navigator.userAgent.includes('AppleWebKit') && !navigator.userAgent.includes('Chrome')) {
411
411
  var pos = this.getPos();
412
412
  if (typeof pos === 'number') {
413
413
  var $tableRowPos = this.view.state.doc.resolve(pos);