@atlaskit/editor-plugin-table 7.2.2 → 7.2.3

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/pm-plugins/drag-and-drop/commands-with-analytics.js +3 -19
  3. package/dist/cjs/utils/drag-menu.js +37 -23
  4. package/dist/cjs/utils/merged-cells.js +66 -1
  5. package/dist/es2019/pm-plugins/drag-and-drop/commands-with-analytics.js +4 -20
  6. package/dist/es2019/utils/drag-menu.js +38 -14
  7. package/dist/es2019/utils/merged-cells.js +73 -0
  8. package/dist/esm/pm-plugins/drag-and-drop/commands-with-analytics.js +4 -20
  9. package/dist/esm/utils/drag-menu.js +36 -22
  10. package/dist/esm/utils/merged-cells.js +65 -0
  11. package/dist/types/utils/drag-menu.d.ts +4 -1
  12. package/dist/types/utils/merged-cells.d.ts +2 -0
  13. package/dist/types-ts4.5/utils/drag-menu.d.ts +4 -1
  14. package/dist/types-ts4.5/utils/merged-cells.d.ts +2 -0
  15. package/package.json +9 -16
  16. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +11 -32
  17. package/src/utils/drag-menu.ts +94 -20
  18. package/src/utils/merged-cells.ts +78 -0
  19. package/tsconfig.dev.json +0 -69
  20. package/tsconfig.json +2 -877
  21. package/examples/99-testing.tsx +0 -140
  22. package/examples/config.jsonc +0 -14
  23. package/src/__tests__/unit/analytics.ts +0 -888
  24. package/src/__tests__/unit/collab.ts +0 -93
  25. package/src/__tests__/unit/commands/go-to-next-cell.ts +0 -173
  26. package/src/__tests__/unit/commands/insert.ts +0 -137
  27. package/src/__tests__/unit/commands/misc.ts +0 -185
  28. package/src/__tests__/unit/commands/sort.ts +0 -128
  29. package/src/__tests__/unit/commands.ts +0 -745
  30. package/src/__tests__/unit/copy-button.ts +0 -22
  31. package/src/__tests__/unit/copy-paste.ts +0 -677
  32. package/src/__tests__/unit/event-handlers/index.ts +0 -125
  33. package/src/__tests__/unit/event-handlers.ts +0 -296
  34. package/src/__tests__/unit/fix-tables.ts +0 -164
  35. package/src/__tests__/unit/get-toolbar-config.ts +0 -127
  36. package/src/__tests__/unit/handlers.ts +0 -98
  37. package/src/__tests__/unit/hover-selection.ts +0 -230
  38. package/src/__tests__/unit/index-with-fake-timers.ts +0 -111
  39. package/src/__tests__/unit/index.ts +0 -912
  40. package/src/__tests__/unit/layout.ts +0 -146
  41. package/src/__tests__/unit/nodeviews/OverflowShadowsObserver.ts +0 -162
  42. package/src/__tests__/unit/nodeviews/TableComponent.tsx +0 -280
  43. package/src/__tests__/unit/nodeviews/TableContainer.tsx +0 -525
  44. package/src/__tests__/unit/nodeviews/cell.ts +0 -132
  45. package/src/__tests__/unit/nodeviews/table.ts +0 -129
  46. package/src/__tests__/unit/pm-plugins/analytics.ts +0 -327
  47. package/src/__tests__/unit/pm-plugins/decorations/column-controls.ts +0 -94
  48. package/src/__tests__/unit/pm-plugins/decorations/column-resizing.ts +0 -176
  49. package/src/__tests__/unit/pm-plugins/decorations/plugin.ts +0 -211
  50. package/src/__tests__/unit/pm-plugins/main.ts +0 -214
  51. package/src/__tests__/unit/pm-plugins/safari-delete-composition-text-issue-workaround.ts +0 -101
  52. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +0 -562
  53. package/src/__tests__/unit/pm-plugins/table-local-id.ts +0 -507
  54. package/src/__tests__/unit/pm-plugins/table-resizing/colgroup.ts +0 -269
  55. package/src/__tests__/unit/pm-plugins/table-resizing/event-handlers.ts +0 -192
  56. package/src/__tests__/unit/pm-plugins/table-resizing/utils/resize-state.ts +0 -33
  57. package/src/__tests__/unit/pm-plugins/table-width.ts +0 -292
  58. package/src/__tests__/unit/sort-column.ts +0 -399
  59. package/src/__tests__/unit/toolbar.ts +0 -512
  60. package/src/__tests__/unit/transforms/delete-columns.ts +0 -597
  61. package/src/__tests__/unit/transforms/delete-rows.ts +0 -620
  62. package/src/__tests__/unit/transforms/merging.ts +0 -392
  63. package/src/__tests__/unit/ui/ContextualMenu.tsx +0 -71
  64. package/src/__tests__/unit/ui/CornerControls.tsx +0 -99
  65. package/src/__tests__/unit/ui/DeleteButton.tsx +0 -38
  66. package/src/__tests__/unit/ui/FixedButton.tsx +0 -217
  67. package/src/__tests__/unit/ui/FloatingContextualButton.tsx +0 -123
  68. package/src/__tests__/unit/ui/FloatingContextualMenu.tsx +0 -68
  69. package/src/__tests__/unit/ui/FloatingDeleteButton.tsx +0 -178
  70. package/src/__tests__/unit/ui/FloatingDragMenu.tsx +0 -511
  71. package/src/__tests__/unit/ui/FloatingInsertButton.tsx +0 -322
  72. package/src/__tests__/unit/ui/NumberColumn.tsx +0 -146
  73. package/src/__tests__/unit/ui/RowControls.tsx +0 -294
  74. package/src/__tests__/unit/ui/RowDragControls.tsx +0 -129
  75. package/src/__tests__/unit/ui/TableFloatingColumnControls.tsx +0 -189
  76. package/src/__tests__/unit/ui/TableFloatingControls.tsx +0 -118
  77. package/src/__tests__/unit/undo-redo.ts +0 -220
  78. package/src/__tests__/unit/utils/analytics.ts +0 -98
  79. package/src/__tests__/unit/utils/collapse.ts +0 -57
  80. package/src/__tests__/unit/utils/column-controls.ts +0 -205
  81. package/src/__tests__/unit/utils/dom.ts +0 -180
  82. package/src/__tests__/unit/utils/merged-cells.ts +0 -156
  83. package/src/__tests__/unit/utils/nodes.ts +0 -79
  84. package/src/__tests__/unit/utils/row-controls.ts +0 -195
  85. package/src/__tests__/unit/utils/table.ts +0 -96
  86. package/src/__tests__/unit/utils.ts +0 -670
  87. package/src/__tests__/visual-regression/__fixtures__/sticky-header-with-horizontal-scroll.json +0 -5228
  88. package/src/__tests__/visual-regression/__fixtures__/table-with-100-numbered-list-items.json +0 -20272
  89. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-column-menu-item-should-remove-the-table-column-on-click-1-snap.png +0 -3
  90. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-column-menu-item-visual-hints-should-be-added-to-the-table-column-on-hover-1-snap.png +0 -3
  91. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-should-remove-the-table-row-on-click-1-snap.png +0 -3
  92. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-visual-hints-should-be-added-to-the-table-row-on-hover-1-snap.png +0 -3
  93. package/src/__tests__/visual-regression/__image_snapshots__/copy-button-ts-floating-toolbar-copy-button-table-target-node-displays-blue-border-when-copy-button-is-hovered-1-snap.png +0 -3
  94. package/src/__tests__/visual-regression/__image_snapshots__/index-ts-snapshot-test-table-numbered-list-should-not-overflow-table-cell-when-there-are-more-than-100-ordered-list-items-1-snap.png +0 -3
  95. package/src/__tests__/visual-regression/__image_snapshots__/index-ts-snapshot-test-table-numbered-list-should-not-overflow-table-cell-when-there-are-more-than-100-ordered-list-items-2-snap.png +0 -3
  96. package/src/__tests__/visual-regression/__image_snapshots__/index-ts-snapshot-test-table-numbered-list-should-not-overflow-table-cell-when-there-are-more-than-100-ordered-list-items-3-snap.png +0 -3
  97. package/src/__tests__/visual-regression/__image_snapshots__/sticky-header-ts-snapshot-test-table-sticky-header-should-align-with-table-cell-when-active-1-snap.png +0 -3
  98. package/src/__tests__/visual-regression/__image_snapshots__/sticky-header-ts-snapshot-test-table-sticky-header-should-align-with-table-cell-when-active-2-snap.png +0 -3
  99. package/src/__tests__/visual-regression/cell-options-menu.ts +0 -101
  100. package/src/__tests__/visual-regression/copy-button.ts +0 -181
  101. package/src/__tests__/visual-regression/index.ts +0 -62
  102. package/src/__tests__/visual-regression/sticky-header.ts +0 -61
@@ -130,4 +130,69 @@ export var hasMergedCellsInBetween = function hasMergedCellsInBetween(indexes, t
130
130
  return mergedCellsInRectArr[1].includes(cell);
131
131
  });
132
132
  };
133
+ };
134
+
135
+ // Checks if any cell in the column with colIndex is merged with a cell in a column to the left or to the right of it.
136
+ // colIndex is a logical index of the column. It starts at 0 and goes up to tableMap.width - 1.
137
+ export var hasMergedCellsWithColumnNextToColumnIndex = function hasMergedCellsWithColumnNextToColumnIndex(colIndex, selection) {
138
+ var table = findTable(selection);
139
+ if (!table) {
140
+ return false;
141
+ }
142
+ var tableMap = TableMap.get(table.node);
143
+ var width = tableMap.width;
144
+ if (width <= 1) {
145
+ return false;
146
+ }
147
+ if (colIndex < 0 || colIndex > width - 1) {
148
+ return false;
149
+ }
150
+ var map = tableMap.map;
151
+ // j is an index in the tableMap.map array. tableMap.map is a flat array.
152
+ // Each item of this array contains a number.
153
+ // The number represents the position of the corresponding cell in the tableMap. It exists for each cell.
154
+ // If there are merged cells, their positions will be represented by the same number.
155
+ var isFirstColumn = colIndex === 0;
156
+ var isLastColumn = colIndex === width - 1;
157
+ for (var j = colIndex; j < map.length; j += width) {
158
+ if (!isFirstColumn && map[j] === map[j - 1] ||
159
+ // compare with a cell in the column on the left
160
+ !isLastColumn && map[j] === map[j + 1] // compare with a cell in the column on the right
161
+ ) {
162
+ return true;
163
+ }
164
+ }
165
+ return false;
166
+ };
167
+
168
+ // Checks if any cell in the row with rowIndex is merged with a cell in a row above or below it.
169
+ export var hasMergedCellsWithRowNextToRowIndex = function hasMergedCellsWithRowNextToRowIndex(rowIndex, selection) {
170
+ var table = findTable(selection);
171
+ if (!table) {
172
+ return false;
173
+ }
174
+ var tableMap = TableMap.get(table.node);
175
+ var height = tableMap.height;
176
+ if (height <= 1) {
177
+ return false;
178
+ }
179
+ if (rowIndex < 0 || rowIndex > height - 1) {
180
+ return false;
181
+ }
182
+ var map = tableMap.map,
183
+ width = tableMap.width; // map is a flat array representing position of each cell in the table.
184
+ var indexOfFirstCellInTheRow = rowIndex * width;
185
+ var indexOfLastCellInTheRow = indexOfFirstCellInTheRow + width - 1;
186
+ var isFirstRow = rowIndex === 0;
187
+ var isLastRow = rowIndex === height - 1;
188
+ // j is an index of a cell in a row
189
+ for (var j = indexOfFirstCellInTheRow; j <= indexOfLastCellInTheRow; j++) {
190
+ if (!isFirstRow && map[j] === map[j - width] ||
191
+ // compare with a cell in the row above
192
+ !isLastRow && map[j] === map[j + width] // compare with a cell in the row below
193
+ ) {
194
+ return true;
195
+ }
196
+ }
197
+ return false;
133
198
  };
@@ -1,9 +1,12 @@
1
1
  /// <reference types="react" />
2
2
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
3
  import type { Command, DropdownOptionT, GetEditorContainerWidth, IconProps } from '@atlaskit/editor-common/types';
4
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
4
5
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
6
  import type { Rect, TableMap } from '@atlaskit/editor-tables/table-map';
6
- import type { TableDirection } from '../types';
7
+ import type { DraggableData, DraggableType, TableDirection } from '../types';
8
+ export declare const getTargetIndex: (selectedIndexes: number[], direction: DraggableData['direction']) => number;
9
+ export declare const canMove: (sourceType: DraggableType, direction: DraggableData['direction'], totalItemsOfSourceTypeCount: number, selection: Selection, selectionRect?: Rect) => boolean;
7
10
  export type DragMenuOptionIdType = 'add_row_above' | 'add_row_below' | 'add_column_left' | 'add_column_right' | 'distribute_columns' | 'clear_cells' | 'delete_row' | 'delete_column' | 'move_column_left' | 'move_column_right' | 'move_row_up' | 'move_row_down' | 'sort_column_asc' | 'sort_column_desc';
8
11
  export interface DragMenuConfig extends DropdownOptionT<Command> {
9
12
  id: DragMenuOptionIdType;
@@ -3,4 +3,6 @@ type MergeType = 'row' | 'column';
3
3
  export declare const hasMergedCellsInColumn: (columnIndexes: number | number[]) => (selection: Selection) => boolean;
4
4
  export declare const hasMergedCellsInRow: (rowIndexes: number | number[]) => (selection: Selection) => boolean;
5
5
  export declare const hasMergedCellsInBetween: (indexes: number[], type: MergeType) => (selection: Selection) => boolean;
6
+ export declare const hasMergedCellsWithColumnNextToColumnIndex: (colIndex: number, selection: Selection) => boolean;
7
+ export declare const hasMergedCellsWithRowNextToRowIndex: (rowIndex: number, selection: Selection) => boolean;
6
8
  export {};
@@ -1,9 +1,12 @@
1
1
  /// <reference types="react" />
2
2
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
3
  import type { Command, DropdownOptionT, GetEditorContainerWidth, IconProps } from '@atlaskit/editor-common/types';
4
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
4
5
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
6
  import type { Rect, TableMap } from '@atlaskit/editor-tables/table-map';
6
- import type { TableDirection } from '../types';
7
+ import type { DraggableData, DraggableType, TableDirection } from '../types';
8
+ export declare const getTargetIndex: (selectedIndexes: number[], direction: DraggableData['direction']) => number;
9
+ export declare const canMove: (sourceType: DraggableType, direction: DraggableData['direction'], totalItemsOfSourceTypeCount: number, selection: Selection, selectionRect?: Rect) => boolean;
7
10
  export type DragMenuOptionIdType = 'add_row_above' | 'add_row_below' | 'add_column_left' | 'add_column_right' | 'distribute_columns' | 'clear_cells' | 'delete_row' | 'delete_column' | 'move_column_left' | 'move_column_right' | 'move_row_up' | 'move_row_down' | 'sort_column_asc' | 'sort_column_desc';
8
11
  export interface DragMenuConfig extends DropdownOptionT<Command> {
9
12
  id: DragMenuOptionIdType;
@@ -3,4 +3,6 @@ type MergeType = 'row' | 'column';
3
3
  export declare const hasMergedCellsInColumn: (columnIndexes: number | number[]) => (selection: Selection) => boolean;
4
4
  export declare const hasMergedCellsInRow: (rowIndexes: number | number[]) => (selection: Selection) => boolean;
5
5
  export declare const hasMergedCellsInBetween: (indexes: number[], type: MergeType) => (selection: Selection) => boolean;
6
+ export declare const hasMergedCellsWithColumnNextToColumnIndex: (colIndex: number, selection: Selection) => boolean;
7
+ export declare const hasMergedCellsWithRowNextToRowIndex: (rowIndex: number, selection: Selection) => boolean;
6
8
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "7.2.2",
3
+ "version": "7.2.3",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -29,15 +29,15 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@atlaskit/adf-schema": "^35.5.1",
32
- "@atlaskit/custom-steps": "^0.0.12",
33
- "@atlaskit/editor-common": "^77.2.0",
32
+ "@atlaskit/custom-steps": "^0.0.13",
33
+ "@atlaskit/editor-common": "^77.3.0",
34
34
  "@atlaskit/editor-palette": "1.5.2",
35
35
  "@atlaskit/editor-plugin-analytics": "^0.4.0",
36
36
  "@atlaskit/editor-plugin-content-insertion": "^0.1.0",
37
37
  "@atlaskit/editor-plugin-guideline": "^0.5.0",
38
38
  "@atlaskit/editor-plugin-selection": "^0.2.0",
39
39
  "@atlaskit/editor-plugin-width": "^0.2.0",
40
- "@atlaskit/editor-prosemirror": "1.1.0",
40
+ "@atlaskit/editor-prosemirror": "3.0.0",
41
41
  "@atlaskit/editor-shared-styles": "^2.9.0",
42
42
  "@atlaskit/editor-tables": "^2.5.0",
43
43
  "@atlaskit/icon": "^22.0.0",
@@ -64,19 +64,7 @@
64
64
  "react-intl-next": "npm:react-intl@^5.18.1"
65
65
  },
66
66
  "devDependencies": {
67
- "@atlaskit/analytics-next": "^9.2.0",
68
- "@atlaskit/editor-plugin-decorations": "^0.2.0",
69
- "@atlaskit/editor-plugin-feature-flags": "^1.0.0",
70
- "@atlaskit/editor-plugin-grid": "^0.3.0",
71
- "@atlaskit/editor-plugin-hyperlink": "^0.8.0",
72
- "@atlaskit/editor-test-helpers": "^18.16.0",
73
- "@atlaskit/visual-regression": "*",
74
67
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
75
- "@atlassian/feature-flags-test-utils": "^0.2.0",
76
- "@testing-library/dom": "^8.17.1",
77
- "@testing-library/react": "^12.1.5",
78
- "@testing-library/react-hooks": "^8.0.1",
79
- "raf-stub": "^2.0.1",
80
68
  "typescript": "~4.9.5"
81
69
  },
82
70
  "af:exports": {
@@ -107,6 +95,11 @@
107
95
  ]
108
96
  }
109
97
  },
98
+ "stricter": {
99
+ "no-unused-dependencies": {
100
+ "checkDevDependencies": true
101
+ }
102
+ },
110
103
  "platform-feature-flags": {
111
104
  "platform.editor.custom-table-width": {
112
105
  "type": "boolean"
@@ -22,10 +22,9 @@ import {
22
22
  getSelectedColumnIndexes,
23
23
  getSelectedRowIndexes,
24
24
  getSelectedTableInfo,
25
- hasMergedCellsInColumn,
26
- hasMergedCellsInRow,
27
25
  } from '../../utils';
28
26
  import { withEditorAnalyticsAPI } from '../../utils/analytics';
27
+ import { canMove, getTargetIndex } from '../../utils/drag-menu';
29
28
 
30
29
  import { clearDropTarget, moveSource } from './commands';
31
30
 
@@ -132,44 +131,24 @@ export const moveSourceWithAnalyticsViaShortcut =
132
131
  const selectedIndexes = isRow
133
132
  ? getSelectedRowIndexes(selectionRect)
134
133
  : getSelectedColumnIndexes(selectionRect);
135
-
136
134
  if (selectedIndexes.length === 0) {
137
135
  return false;
138
136
  }
139
137
 
140
- // const sourceIndex = selectedIndexes[0];
141
- // we can move only by one row/column
142
- // 'direction' can only be 1 (for right or down) or -1 (for left or up)
143
- const targetIndex =
144
- Math[direction < 0 ? 'min' : 'max'](...selectedIndexes) + direction;
145
-
146
- // We can move only if targetIndex is a positive number and is not higher than the total number of rows/columns.
147
138
  const { totalRowCount, totalColumnCount } = getSelectedTableInfo(selection);
148
- const isValidTargetIndex =
149
- targetIndex < 0
150
- ? false
151
- : isRow
152
- ? targetIndex <= totalRowCount - 1
153
- : targetIndex <= totalColumnCount - 1;
154
-
155
- if (!isValidTargetIndex) {
156
- return false;
157
- }
158
-
159
- // We can move only if there are no merged cells in the source or target row/column
160
- const hasMergedCellsInSource = isRow
161
- ? hasMergedCellsInRow(selectedIndexes)(selection)
162
- : hasMergedCellsInColumn(selectedIndexes)(selection);
163
- if (hasMergedCellsInSource) {
139
+ if (
140
+ !canMove(
141
+ sourceType,
142
+ direction,
143
+ isRow ? totalRowCount : totalColumnCount,
144
+ selection,
145
+ selectionRect,
146
+ )
147
+ ) {
164
148
  return false;
165
149
  }
166
150
 
167
- const hasMergedCellsInTarget = isRow
168
- ? hasMergedCellsInRow(targetIndex)(selection)
169
- : hasMergedCellsInColumn(targetIndex)(selection);
170
- if (hasMergedCellsInTarget) {
171
- return false;
172
- }
151
+ const targetIndex = getTargetIndex(selectedIndexes, direction);
173
152
 
174
153
  return moveSourceWithAnalytics(editorAnalyticsAPI)(
175
154
  INPUT_METHOD.SHORTCUT,
@@ -22,7 +22,10 @@ import type {
22
22
  GetEditorContainerWidth,
23
23
  IconProps,
24
24
  } from '@atlaskit/editor-common/types';
25
- import type { EditorState } from '@atlaskit/editor-prosemirror/state';
25
+ import type {
26
+ EditorState,
27
+ Selection,
28
+ } from '@atlaskit/editor-prosemirror/state';
26
29
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
27
30
  import type { Rect, TableMap } from '@atlaskit/editor-tables/table-map';
28
31
  import ArrowDownIcon from '@atlaskit/icon/glyph/arrow-down';
@@ -47,7 +50,7 @@ import { distributeColumnsWidths } from '../pm-plugins/table-resizing/commands';
47
50
  import { getNewResizeStateFromSelectedColumns } from '../pm-plugins/table-resizing/utils/resize-state';
48
51
  import { getClosestSelectionRect } from '../toolbar';
49
52
  import { deleteRows } from '../transforms';
50
- import type { TableDirection } from '../types';
53
+ import type { DraggableData, DraggableType, TableDirection } from '../types';
51
54
  import {
52
55
  AddColLeftIcon,
53
56
  AddColRightIcon,
@@ -55,12 +58,61 @@ import {
55
58
  AddRowBelowIcon,
56
59
  } from '../ui/icons';
57
60
 
61
+ import {
62
+ hasMergedCellsInColumn,
63
+ hasMergedCellsInRow,
64
+ hasMergedCellsWithColumnNextToColumnIndex,
65
+ hasMergedCellsWithRowNextToRowIndex,
66
+ } from './merged-cells';
58
67
  import { getSelectedColumnIndexes, getSelectedRowIndexes } from './selection';
59
68
 
60
- const canDecrease = (index?: number, min: number = 0) =>
61
- index !== undefined && index > min;
62
- const canIncrease = (index?: number, max: number = 0) =>
63
- index !== undefined && index < max;
69
+ export const getTargetIndex = (
70
+ selectedIndexes: number[],
71
+ direction: DraggableData['direction'],
72
+ ) => Math[direction < 0 ? 'min' : 'max'](...selectedIndexes) + direction;
73
+
74
+ export const canMove = (
75
+ sourceType: DraggableType,
76
+ direction: DraggableData['direction'],
77
+ totalItemsOfSourceTypeCount: number,
78
+ selection: Selection,
79
+ selectionRect?: Rect,
80
+ ) => {
81
+ if (!selectionRect) {
82
+ return false;
83
+ }
84
+
85
+ const isRow = sourceType === 'table-row';
86
+ const selectedIndexes = isRow
87
+ ? getSelectedRowIndexes(selectionRect)
88
+ : getSelectedColumnIndexes(selectionRect);
89
+ const targetIndex = getTargetIndex(selectedIndexes, direction);
90
+
91
+ const isValidTargetIndex =
92
+ targetIndex >= 0 && targetIndex < totalItemsOfSourceTypeCount;
93
+ if (!isValidTargetIndex) {
94
+ return false;
95
+ }
96
+
97
+ // We can't move column when target has merges with other columns
98
+ // We can't move row when target has merges with other rows
99
+ const hasMergedCellsInTarget = isRow
100
+ ? hasMergedCellsWithRowNextToRowIndex(targetIndex, selection)
101
+ : hasMergedCellsWithColumnNextToColumnIndex(targetIndex, selection);
102
+ if (hasMergedCellsInTarget) {
103
+ return false;
104
+ }
105
+
106
+ // Currently we can't move in any direction if there are merged cells in the source
107
+ const hasMergedCellsInSource = isRow
108
+ ? hasMergedCellsInRow(selectedIndexes)(selection)
109
+ : hasMergedCellsInColumn(selectedIndexes)(selection);
110
+ if (hasMergedCellsInSource) {
111
+ return false;
112
+ }
113
+
114
+ return true;
115
+ };
64
116
 
65
117
  const isDistributeColumnsEnabled = (state: EditorState) => {
66
118
  const rect = getClosestSelectionRect(state);
@@ -135,6 +187,8 @@ export const getDragMenuConfig = (
135
187
  keymap: addColumnAfter,
136
188
  },
137
189
  ];
190
+
191
+ const { selection } = editorView.state;
138
192
  const moveOptions =
139
193
  direction === 'row'
140
194
  ? [
@@ -142,8 +196,15 @@ export const getDragMenuConfig = (
142
196
  label: 'up',
143
197
  icon: ArrowUpIcon,
144
198
  keymap: moveRowUp,
145
- canMove: (selectionRect?: Rect) =>
146
- canDrag && canDecrease(selectionRect?.top),
199
+ canMove:
200
+ canDrag &&
201
+ canMove(
202
+ 'table-row',
203
+ -1,
204
+ tableMap?.height ?? 0,
205
+ selection,
206
+ selectionRect,
207
+ ),
147
208
  getOriginIndexes: getSelectedRowIndexes,
148
209
  getTargetIndex: (selectionRect: Rect) => selectionRect.top - 1,
149
210
  },
@@ -151,11 +212,14 @@ export const getDragMenuConfig = (
151
212
  label: 'down',
152
213
  icon: ArrowDownIcon,
153
214
  keymap: moveRowDown,
154
- canMove: (selectionRect?: Rect) =>
215
+ canMove:
155
216
  canDrag &&
156
- canIncrease(
157
- (selectionRect?.bottom ?? 0) - 1,
158
- (tableMap?.height ?? 0) - 1,
217
+ canMove(
218
+ 'table-row',
219
+ 1,
220
+ tableMap?.height ?? 0,
221
+ selection,
222
+ selectionRect,
159
223
  ),
160
224
  getOriginIndexes: getSelectedRowIndexes,
161
225
  getTargetIndex: (selectionRect: Rect) => selectionRect.bottom,
@@ -166,8 +230,15 @@ export const getDragMenuConfig = (
166
230
  label: 'left',
167
231
  icon: ArrowLeftIcon,
168
232
  keymap: moveColumnLeft,
169
- canMove: (selectionRect?: Rect) =>
170
- canDrag && canDecrease(selectionRect?.left),
233
+ canMove:
234
+ canDrag &&
235
+ canMove(
236
+ 'table-column',
237
+ -1,
238
+ tableMap?.width ?? 0,
239
+ selection,
240
+ selectionRect,
241
+ ),
171
242
  getOriginIndexes: getSelectedColumnIndexes,
172
243
  getTargetIndex: (selectionRect: Rect) => selectionRect.left - 1,
173
244
  },
@@ -175,11 +246,14 @@ export const getDragMenuConfig = (
175
246
  label: 'right',
176
247
  icon: ArrowRightIcon,
177
248
  keymap: moveColumnRight,
178
- canMove: (selectionRect?: Rect) =>
249
+ canMove:
179
250
  canDrag &&
180
- canIncrease(
181
- (selectionRect?.right ?? 0) - 1,
182
- (tableMap?.width ?? 0) - 1,
251
+ canMove(
252
+ 'table-column',
253
+ 1,
254
+ tableMap?.width ?? 0,
255
+ selection,
256
+ selectionRect,
183
257
  ),
184
258
  getOriginIndexes: getSelectedColumnIndexes,
185
259
  getTargetIndex: (selectionRect: Rect) => selectionRect.right,
@@ -275,10 +349,10 @@ export const getDragMenuConfig = (
275
349
  ({ label, canMove, icon, keymap, getOriginIndexes, getTargetIndex }) => ({
276
350
  id: `move_${direction}_${label}`,
277
351
  title: `Move ${direction} ${label}`,
278
- disabled: !canMove(selectionRect),
352
+ disabled: !canMove,
279
353
  icon,
280
354
  onClick: (state: EditorState, dispatch?: CommandDispatch) => {
281
- if (canMove(selectionRect)) {
355
+ if (canMove) {
282
356
  requestAnimationFrame(() => {
283
357
  moveSourceWithAnalytics(editorAnalyticsAPI)(
284
358
  INPUT_METHOD.TABLE_CONTEXT_MENU,
@@ -147,3 +147,81 @@ export const hasMergedCellsInBetween =
147
147
  mergedCellsInRectArr[1].includes(cell),
148
148
  );
149
149
  };
150
+
151
+ // Checks if any cell in the column with colIndex is merged with a cell in a column to the left or to the right of it.
152
+ // colIndex is a logical index of the column. It starts at 0 and goes up to tableMap.width - 1.
153
+ export const hasMergedCellsWithColumnNextToColumnIndex = (
154
+ colIndex: number,
155
+ selection: Selection,
156
+ ) => {
157
+ const table = findTable(selection);
158
+ if (!table) {
159
+ return false;
160
+ }
161
+
162
+ const tableMap = TableMap.get(table.node);
163
+ const { width } = tableMap;
164
+ if (width <= 1) {
165
+ return false;
166
+ }
167
+
168
+ if (colIndex < 0 || colIndex > width - 1) {
169
+ return false;
170
+ }
171
+
172
+ const { map } = tableMap;
173
+ // j is an index in the tableMap.map array. tableMap.map is a flat array.
174
+ // Each item of this array contains a number.
175
+ // The number represents the position of the corresponding cell in the tableMap. It exists for each cell.
176
+ // If there are merged cells, their positions will be represented by the same number.
177
+ const isFirstColumn = colIndex === 0;
178
+ const isLastColumn = colIndex === width - 1;
179
+ for (let j = colIndex; j < map.length; j += width) {
180
+ if (
181
+ (!isFirstColumn && map[j] === map[j - 1]) || // compare with a cell in the column on the left
182
+ (!isLastColumn && map[j] === map[j + 1]) // compare with a cell in the column on the right
183
+ ) {
184
+ return true;
185
+ }
186
+ }
187
+
188
+ return false;
189
+ };
190
+
191
+ // Checks if any cell in the row with rowIndex is merged with a cell in a row above or below it.
192
+ export const hasMergedCellsWithRowNextToRowIndex = (
193
+ rowIndex: number, // logical row index in the table. It starts at 0 and goes up to tableMap.height - 1.
194
+ selection: Selection,
195
+ ) => {
196
+ const table = findTable(selection);
197
+ if (!table) {
198
+ return false;
199
+ }
200
+
201
+ const tableMap = TableMap.get(table.node);
202
+ const { height } = tableMap;
203
+ if (height <= 1) {
204
+ return false;
205
+ }
206
+
207
+ if (rowIndex < 0 || rowIndex > height - 1) {
208
+ return false;
209
+ }
210
+
211
+ const { map, width } = tableMap; // map is a flat array representing position of each cell in the table.
212
+ const indexOfFirstCellInTheRow = rowIndex * width;
213
+ const indexOfLastCellInTheRow = indexOfFirstCellInTheRow + width - 1;
214
+ const isFirstRow = rowIndex === 0;
215
+ const isLastRow = rowIndex === height - 1;
216
+ // j is an index of a cell in a row
217
+ for (let j = indexOfFirstCellInTheRow; j <= indexOfLastCellInTheRow; j++) {
218
+ if (
219
+ (!isFirstRow && map[j] === map[j - width]) || // compare with a cell in the row above
220
+ (!isLastRow && map[j] === map[j + width]) // compare with a cell in the row below
221
+ ) {
222
+ return true;
223
+ }
224
+ }
225
+
226
+ return false;
227
+ };
package/tsconfig.dev.json CHANGED
@@ -36,83 +36,14 @@
36
36
  {
37
37
  "path": "tsconfig.app.json"
38
38
  },
39
- {
40
- "path": "../../analytics/analytics-next/tsconfig.app.json"
41
- },
42
- {
43
- "path": "../../design-system/button/tsconfig.app.json"
44
- },
45
- {
46
- "path": "../custom-steps/tsconfig.app.json"
47
- },
48
39
  {
49
40
  "path": "../../../build/website/docs/tsconfig.app.json"
50
41
  },
51
- {
52
- "path": "../editor-common/tsconfig.app.json"
53
- },
54
42
  {
55
43
  "path": "../editor-core/tsconfig.app.json"
56
44
  },
57
- {
58
- "path": "../editor-plugin-analytics/tsconfig.app.json"
59
- },
60
- {
61
- "path": "../editor-plugin-content-insertion/tsconfig.app.json"
62
- },
63
- {
64
- "path": "../editor-plugin-decorations/tsconfig.app.json"
65
- },
66
- {
67
- "path": "../editor-plugin-feature-flags/tsconfig.app.json"
68
- },
69
- {
70
- "path": "../editor-plugin-grid/tsconfig.app.json"
71
- },
72
- {
73
- "path": "../editor-plugin-guideline/tsconfig.app.json"
74
- },
75
- {
76
- "path": "../editor-plugin-selection/tsconfig.app.json"
77
- },
78
- {
79
- "path": "../editor-plugin-width/tsconfig.app.json"
80
- },
81
- {
82
- "path": "../editor-shared-styles/tsconfig.app.json"
83
- },
84
- {
85
- "path": "../editor-tables/tsconfig.app.json"
86
- },
87
- {
88
- "path": "../editor-test-helpers/tsconfig.app.json"
89
- },
90
- {
91
- "path": "../../linking-platform/link-provider/tsconfig.app.json"
92
- },
93
- {
94
- "path": "../../design-system/logo/tsconfig.app.json"
95
- },
96
- {
97
- "path": "../../media/media-integration-test-helpers/tsconfig.app.json"
98
- },
99
- {
100
- "path": "../../platform/feature-flags/tsconfig.app.json"
101
- },
102
- {
103
- "path": "../synchrony-test-helpers/tsconfig.app.json"
104
- },
105
- {
106
- "path": "../../design-system/theme/tsconfig.app.json"
107
- },
108
45
  {
109
46
  "path": "../../design-system/tokens/tsconfig.app.json"
110
- },
111
- {
112
- "path": "../../../build/test-tooling/visual-regression/tsconfig.app.json"
113
- },
114
- {
115
- "path": "../../platform/feature-flags-test-utils/tsconfig.app.json"
116
47
  }
117
48
  ]
118
49
  }