@atlaskit/editor-plugin-table 7.2.2 → 7.3.0

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 (149) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/commands/column-resize.js +115 -45
  3. package/dist/cjs/commands/go-to-next-cell.js +7 -11
  4. package/dist/cjs/commands/misc.js +3 -2
  5. package/dist/cjs/commands/selection.js +3 -3
  6. package/dist/cjs/event-handlers.js +38 -25
  7. package/dist/cjs/pm-plugins/drag-and-drop/commands-with-analytics.js +3 -19
  8. package/dist/cjs/pm-plugins/keymap.js +1 -0
  9. package/dist/cjs/pm-plugins/main.js +43 -9
  10. package/dist/cjs/pm-plugins/table-resizing/event-handlers.js +37 -7
  11. package/dist/cjs/pm-plugins/table-resizing/plugin.js +20 -6
  12. package/dist/cjs/reducer.js +5 -2
  13. package/dist/cjs/utils/drag-menu.js +37 -23
  14. package/dist/cjs/utils/merged-cells.js +66 -1
  15. package/dist/es2019/commands/column-resize.js +100 -35
  16. package/dist/es2019/commands/go-to-next-cell.js +7 -9
  17. package/dist/es2019/commands/misc.js +3 -2
  18. package/dist/es2019/commands/selection.js +5 -5
  19. package/dist/es2019/event-handlers.js +17 -3
  20. package/dist/es2019/pm-plugins/drag-and-drop/commands-with-analytics.js +4 -20
  21. package/dist/es2019/pm-plugins/keymap.js +3 -2
  22. package/dist/es2019/pm-plugins/main.js +41 -5
  23. package/dist/es2019/pm-plugins/table-resizing/event-handlers.js +37 -4
  24. package/dist/es2019/pm-plugins/table-resizing/plugin.js +16 -1
  25. package/dist/es2019/reducer.js +5 -2
  26. package/dist/es2019/utils/drag-menu.js +38 -14
  27. package/dist/es2019/utils/merged-cells.js +73 -0
  28. package/dist/esm/commands/column-resize.js +105 -35
  29. package/dist/esm/commands/go-to-next-cell.js +7 -11
  30. package/dist/esm/commands/misc.js +3 -2
  31. package/dist/esm/commands/selection.js +5 -5
  32. package/dist/esm/event-handlers.js +38 -25
  33. package/dist/esm/pm-plugins/drag-and-drop/commands-with-analytics.js +4 -20
  34. package/dist/esm/pm-plugins/keymap.js +3 -2
  35. package/dist/esm/pm-plugins/main.js +38 -4
  36. package/dist/esm/pm-plugins/table-resizing/event-handlers.js +34 -4
  37. package/dist/esm/pm-plugins/table-resizing/plugin.js +15 -1
  38. package/dist/esm/reducer.js +5 -2
  39. package/dist/esm/utils/drag-menu.js +36 -22
  40. package/dist/esm/utils/merged-cells.js +65 -0
  41. package/dist/types/commands/column-resize.d.ts +2 -0
  42. package/dist/types/commands/misc.d.ts +1 -1
  43. package/dist/types/types.d.ts +16 -0
  44. package/dist/types/utils/drag-menu.d.ts +4 -1
  45. package/dist/types/utils/merged-cells.d.ts +2 -0
  46. package/dist/types-ts4.5/commands/column-resize.d.ts +2 -0
  47. package/dist/types-ts4.5/commands/misc.d.ts +1 -1
  48. package/dist/types-ts4.5/types.d.ts +16 -0
  49. package/dist/types-ts4.5/utils/drag-menu.d.ts +4 -1
  50. package/dist/types-ts4.5/utils/merged-cells.d.ts +2 -0
  51. package/package.json +10 -17
  52. package/src/commands/column-resize.ts +155 -40
  53. package/src/commands/go-to-next-cell.ts +6 -15
  54. package/src/commands/misc.ts +2 -0
  55. package/src/commands/selection.ts +5 -5
  56. package/src/event-handlers.ts +21 -4
  57. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +11 -32
  58. package/src/pm-plugins/keymap.ts +3 -0
  59. package/src/pm-plugins/main.ts +47 -2
  60. package/src/pm-plugins/table-resizing/event-handlers.ts +33 -5
  61. package/src/pm-plugins/table-resizing/plugin.ts +18 -1
  62. package/src/reducer.ts +5 -2
  63. package/src/types.ts +16 -0
  64. package/src/utils/drag-menu.ts +94 -20
  65. package/src/utils/merged-cells.ts +78 -0
  66. package/tsconfig.dev.json +0 -69
  67. package/tsconfig.json +2 -877
  68. package/examples/99-testing.tsx +0 -140
  69. package/examples/config.jsonc +0 -14
  70. package/src/__tests__/unit/analytics.ts +0 -888
  71. package/src/__tests__/unit/collab.ts +0 -93
  72. package/src/__tests__/unit/commands/go-to-next-cell.ts +0 -173
  73. package/src/__tests__/unit/commands/insert.ts +0 -137
  74. package/src/__tests__/unit/commands/misc.ts +0 -185
  75. package/src/__tests__/unit/commands/sort.ts +0 -128
  76. package/src/__tests__/unit/commands.ts +0 -745
  77. package/src/__tests__/unit/copy-button.ts +0 -22
  78. package/src/__tests__/unit/copy-paste.ts +0 -677
  79. package/src/__tests__/unit/event-handlers/index.ts +0 -125
  80. package/src/__tests__/unit/event-handlers.ts +0 -296
  81. package/src/__tests__/unit/fix-tables.ts +0 -164
  82. package/src/__tests__/unit/get-toolbar-config.ts +0 -127
  83. package/src/__tests__/unit/handlers.ts +0 -98
  84. package/src/__tests__/unit/hover-selection.ts +0 -230
  85. package/src/__tests__/unit/index-with-fake-timers.ts +0 -111
  86. package/src/__tests__/unit/index.ts +0 -912
  87. package/src/__tests__/unit/layout.ts +0 -146
  88. package/src/__tests__/unit/nodeviews/OverflowShadowsObserver.ts +0 -162
  89. package/src/__tests__/unit/nodeviews/TableComponent.tsx +0 -280
  90. package/src/__tests__/unit/nodeviews/TableContainer.tsx +0 -525
  91. package/src/__tests__/unit/nodeviews/cell.ts +0 -132
  92. package/src/__tests__/unit/nodeviews/table.ts +0 -129
  93. package/src/__tests__/unit/pm-plugins/analytics.ts +0 -327
  94. package/src/__tests__/unit/pm-plugins/decorations/column-controls.ts +0 -94
  95. package/src/__tests__/unit/pm-plugins/decorations/column-resizing.ts +0 -176
  96. package/src/__tests__/unit/pm-plugins/decorations/plugin.ts +0 -211
  97. package/src/__tests__/unit/pm-plugins/main.ts +0 -214
  98. package/src/__tests__/unit/pm-plugins/safari-delete-composition-text-issue-workaround.ts +0 -101
  99. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +0 -562
  100. package/src/__tests__/unit/pm-plugins/table-local-id.ts +0 -507
  101. package/src/__tests__/unit/pm-plugins/table-resizing/colgroup.ts +0 -269
  102. package/src/__tests__/unit/pm-plugins/table-resizing/event-handlers.ts +0 -192
  103. package/src/__tests__/unit/pm-plugins/table-resizing/utils/resize-state.ts +0 -33
  104. package/src/__tests__/unit/pm-plugins/table-width.ts +0 -292
  105. package/src/__tests__/unit/sort-column.ts +0 -399
  106. package/src/__tests__/unit/toolbar.ts +0 -512
  107. package/src/__tests__/unit/transforms/delete-columns.ts +0 -597
  108. package/src/__tests__/unit/transforms/delete-rows.ts +0 -620
  109. package/src/__tests__/unit/transforms/merging.ts +0 -392
  110. package/src/__tests__/unit/ui/ContextualMenu.tsx +0 -71
  111. package/src/__tests__/unit/ui/CornerControls.tsx +0 -99
  112. package/src/__tests__/unit/ui/DeleteButton.tsx +0 -38
  113. package/src/__tests__/unit/ui/FixedButton.tsx +0 -217
  114. package/src/__tests__/unit/ui/FloatingContextualButton.tsx +0 -123
  115. package/src/__tests__/unit/ui/FloatingContextualMenu.tsx +0 -68
  116. package/src/__tests__/unit/ui/FloatingDeleteButton.tsx +0 -178
  117. package/src/__tests__/unit/ui/FloatingDragMenu.tsx +0 -511
  118. package/src/__tests__/unit/ui/FloatingInsertButton.tsx +0 -322
  119. package/src/__tests__/unit/ui/NumberColumn.tsx +0 -146
  120. package/src/__tests__/unit/ui/RowControls.tsx +0 -294
  121. package/src/__tests__/unit/ui/RowDragControls.tsx +0 -129
  122. package/src/__tests__/unit/ui/TableFloatingColumnControls.tsx +0 -189
  123. package/src/__tests__/unit/ui/TableFloatingControls.tsx +0 -118
  124. package/src/__tests__/unit/undo-redo.ts +0 -220
  125. package/src/__tests__/unit/utils/analytics.ts +0 -98
  126. package/src/__tests__/unit/utils/collapse.ts +0 -57
  127. package/src/__tests__/unit/utils/column-controls.ts +0 -205
  128. package/src/__tests__/unit/utils/dom.ts +0 -180
  129. package/src/__tests__/unit/utils/merged-cells.ts +0 -156
  130. package/src/__tests__/unit/utils/nodes.ts +0 -79
  131. package/src/__tests__/unit/utils/row-controls.ts +0 -195
  132. package/src/__tests__/unit/utils/table.ts +0 -96
  133. package/src/__tests__/unit/utils.ts +0 -670
  134. package/src/__tests__/visual-regression/__fixtures__/sticky-header-with-horizontal-scroll.json +0 -5228
  135. package/src/__tests__/visual-regression/__fixtures__/table-with-100-numbered-list-items.json +0 -20272
  136. 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
  137. 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
  138. 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
  139. 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
  140. 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
  141. 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
  142. 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
  143. 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
  144. 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
  145. 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
  146. package/src/__tests__/visual-regression/cell-options-menu.ts +0 -101
  147. package/src/__tests__/visual-regression/copy-button.ts +0 -181
  148. package/src/__tests__/visual-regression/index.ts +0 -62
  149. package/src/__tests__/visual-regression/sticky-header.ts +0 -61
@@ -38,12 +38,16 @@ import {
38
38
  findParentNodeOfType,
39
39
  } from '@atlaskit/editor-prosemirror/utils';
40
40
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
41
+ import { TableMap } from '@atlaskit/editor-tables';
42
+ import { findTable } from '@atlaskit/editor-tables/utils';
43
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
41
44
 
42
45
  import {
43
46
  addBoldInEmptyHeaderCells,
44
47
  clearHoverSelection,
45
48
  setTableRef,
46
49
  } from '../commands';
50
+ import { stopKeyboardColumnResizing } from '../commands/column-resize';
47
51
  import {
48
52
  removeResizeHandleDecorations,
49
53
  transformSliceRemoveCellBackgroundColor,
@@ -202,7 +206,7 @@ export const createPlugin = (
202
206
  editorViewRef = editorView;
203
207
 
204
208
  return {
205
- update: (view: EditorView) => {
209
+ update: (view: EditorView, prevState: EditorState) => {
206
210
  const { state, dispatch } = view;
207
211
  const { selection } = state;
208
212
  const pluginState = getPluginState(state);
@@ -218,6 +222,39 @@ export const createPlugin = (
218
222
  'table',
219
223
  ) || undefined;
220
224
  }
225
+ const tableNode = findTable(state.selection);
226
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
227
+ // when cursor leaves the table we need to stop column resizing
228
+ const pluginPrevState = getPluginState(prevState);
229
+ const isStopKeyboardColumResizing =
230
+ pluginPrevState.isResizeHandleWidgetAdded &&
231
+ pluginPrevState.isKeyboardResize;
232
+ if (isStopKeyboardColumResizing) {
233
+ const isTableNodesDifferent =
234
+ pluginPrevState?.tableNode !== tableNode?.node;
235
+ if (
236
+ pluginPrevState?.tableNode &&
237
+ tableNode &&
238
+ isTableNodesDifferent
239
+ ) {
240
+ const oldRowsNumber = TableMap.get(
241
+ pluginPrevState.tableNode,
242
+ ).height;
243
+ const newRowsNumber = TableMap.get(tableNode.node).height;
244
+ if (
245
+ oldRowsNumber !== newRowsNumber || // Add/delete row
246
+ tableNode.node.attrs.localId !==
247
+ pluginPrevState.tableNode.attrs.localId
248
+ ) {
249
+ // Jump to another table
250
+ stopKeyboardColumnResizing()(state, dispatch);
251
+ }
252
+ } else if (!tableNode) {
253
+ // selection outside of table
254
+ stopKeyboardColumnResizing()(state, dispatch);
255
+ }
256
+ }
257
+ }
221
258
  }
222
259
 
223
260
  if (pluginState.tableRef !== tableRef) {
@@ -333,7 +370,15 @@ export const createPlugin = (
333
370
  const maybeTr = closestElement(domRef as HTMLElement | undefined, 'tr');
334
371
  return maybeTr ? maybeTr.classList.contains('sticky') : false;
335
372
  },
336
- handleTextInput: ({ state, dispatch }, _from, _to, text) => {
373
+ handleTextInput: (view, _from, _to, text) => {
374
+ const { state, dispatch } = view;
375
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
376
+ const { isKeyboardResize } = getPluginState(state);
377
+ if (isKeyboardResize) {
378
+ stopKeyboardColumnResizing()(state, dispatch);
379
+ return false;
380
+ }
381
+ }
337
382
  const tr = replaceSelectedTable(
338
383
  state,
339
384
  text,
@@ -18,9 +18,11 @@ import { TableMap } from '@atlaskit/editor-tables/table-map';
18
18
  import { getSelectionRect } from '@atlaskit/editor-tables/utils';
19
19
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
20
20
 
21
+ import { stopKeyboardColumnResizing } from '../../commands/column-resize';
21
22
  import { updateResizeHandleDecorations } from '../../commands/misc';
22
23
  import { updateColumnWidths } from '../../transforms';
23
24
  import { getSelectedColumnIndexes } from '../../utils';
25
+ import { getPluginState as getTablePluginState } from '../plugin-factory';
24
26
  import { META_KEYS } from '../table-analytics';
25
27
 
26
28
  import { evenColumns, setDragging, stopResizing } from './commands';
@@ -54,6 +56,7 @@ export const handleMouseDown = (
54
56
  ) {
55
57
  return false;
56
58
  }
59
+ const { isKeyboardResize } = getTablePluginState(state);
57
60
  event.preventDefault();
58
61
 
59
62
  const tr = view.state.tr;
@@ -147,6 +150,7 @@ export const handleMouseDown = (
147
150
  const { clientX } = event;
148
151
  const { state, dispatch } = view;
149
152
  const { dragging, resizeHandlePos } = getPluginState(state);
153
+ const { isTableHovered } = getTablePluginState(state);
150
154
  if (resizeHandlePos === null) {
151
155
  return stopResizing()(state, dispatch);
152
156
  }
@@ -160,9 +164,20 @@ export const handleMouseDown = (
160
164
  const start = $cell.start(-1);
161
165
  const table = $cell.node(-1);
162
166
 
163
- // If we let go in the same place we started, dont need to do anything.
167
+ // If we let go in the same place we started, don't need to do anything.
164
168
  if (dragging && clientX === dragging.startX) {
165
- return stopResizing()(state, dispatch);
169
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
170
+ if (isKeyboardResize || !isTableHovered) {
171
+ /** if column resize had started via keyboard but continued by mouse
172
+ * or mouse pointer leaves the table but mouse button still pressed
173
+ */
174
+ return stopKeyboardColumnResizing()(state, dispatch, view);
175
+ } else {
176
+ return stopResizing()(state, dispatch);
177
+ }
178
+ } else {
179
+ return stopResizing()(state, dispatch);
180
+ }
166
181
  }
167
182
 
168
183
  let { tr } = state;
@@ -211,8 +226,18 @@ export const handleMouseDown = (
211
226
  })(tr);
212
227
  }
213
228
  }
214
-
215
- return stopResizing(tr)(state, dispatch);
229
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
230
+ if (isKeyboardResize || !isTableHovered) {
231
+ /** if column resize had started via keyboard but continued by mouse
232
+ * or mouse pointer leaves the table but mouse button still pressed
233
+ */
234
+ return stopKeyboardColumnResizing(tr)(state, dispatch, view);
235
+ } else {
236
+ return stopResizing(tr)(state, dispatch);
237
+ }
238
+ } else {
239
+ return stopResizing(tr)(state, dispatch);
240
+ }
216
241
  }
217
242
  }
218
243
 
@@ -220,11 +245,14 @@ export const handleMouseDown = (
220
245
  const { clientX, which } = event;
221
246
  const { state } = view;
222
247
  const { dragging, resizeHandlePos } = getPluginState(state);
248
+ const { isTableHovered } = getTablePluginState(state);
223
249
  if (
224
250
  !which ||
225
251
  !dragging ||
226
252
  resizeHandlePos === null ||
227
- !pointsAtCell(state.doc.resolve(resizeHandlePos))
253
+ !pointsAtCell(state.doc.resolve(resizeHandlePos)) ||
254
+ (!isTableHovered &&
255
+ getBooleanFF('platform.editor.a11y-column-resizing_emcvz'))
228
256
  ) {
229
257
  return finish(event);
230
258
  }
@@ -7,9 +7,11 @@ import type {
7
7
  GetEditorContainerWidth,
8
8
  GetEditorFeatureFlags,
9
9
  } from '@atlaskit/editor-common/types';
10
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
10
11
 
11
12
  import { TableCssClassName as ClassName } from '../../types';
12
13
  import type { ColumnResizingPluginState } from '../../types';
14
+ import { getPluginState as getTablePluginState } from '../plugin-factory';
13
15
 
14
16
  import { setResizeHandlePos } from './commands';
15
17
  import { handleMouseDown } from './event-handlers';
@@ -54,7 +56,22 @@ export function createPlugin(
54
56
  getResizeCellPos(view, event as MouseEvent);
55
57
 
56
58
  const { dragging } = getPluginState(state);
57
- if (resizeHandlePos !== null && !dragging) {
59
+ let isColumnKeyboardResizeStarted = false;
60
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
61
+ /*
62
+ We need to start listening mouse events if column resize started from keyboard.
63
+ This will allow continue resizing via mouse
64
+ */
65
+ const { isKeyboardResize } = getTablePluginState(state);
66
+ if (isKeyboardResize) {
67
+ isColumnKeyboardResizeStarted = isKeyboardResize;
68
+ }
69
+ }
70
+
71
+ if (
72
+ resizeHandlePos !== null &&
73
+ (!dragging || isColumnKeyboardResizeStarted)
74
+ ) {
58
75
  if (
59
76
  handleMouseDown(
60
77
  view,
package/src/reducer.ts CHANGED
@@ -82,14 +82,15 @@ export default (
82
82
  resizeHandleColumnIndex: undefined,
83
83
  resizeHandleRowIndex: undefined,
84
84
  };
85
-
85
+ case 'START_KEYBOARD_COLUMN_RESIZE':
86
86
  case 'ADD_RESIZE_HANDLE_DECORATIONS':
87
87
  if (
88
88
  action.data.resizeHandleColumnIndex ===
89
89
  pluginState.resizeHandleColumnIndex &&
90
90
  action.data.resizeHandleRowIndex === pluginState.resizeHandleRowIndex &&
91
91
  action.data.resizeHandleIncludeTooltip ===
92
- pluginState.resizeHandleIncludeTooltip
92
+ pluginState.resizeHandleIncludeTooltip &&
93
+ action.data.isKeyboardResize === pluginState.isKeyboardResize
93
94
  ) {
94
95
  return pluginState;
95
96
  }
@@ -128,6 +129,7 @@ export default (
128
129
  resizeHandleIncludeTooltip ?? pluginState.resizeHandleIncludeTooltip,
129
130
  };
130
131
 
132
+ case 'STOP_KEYBOARD_COLUMN_RESIZE':
131
133
  case 'REMOVE_RESIZE_HANDLE_DECORATIONS':
132
134
  if (!pluginState.isResizeHandleWidgetAdded) {
133
135
  return pluginState;
@@ -139,6 +141,7 @@ export default (
139
141
  resizeHandleColumnIndex: undefined,
140
142
  resizeHandleRowIndex: undefined,
141
143
  isResizeHandleWidgetAdded: false,
144
+ isKeyboardResize: undefined,
142
145
  };
143
146
 
144
147
  case 'SET_TABLE_REF':
package/src/types.ts CHANGED
@@ -119,6 +119,7 @@ export interface TablePluginState {
119
119
  resizeHandleRowIndex?: number;
120
120
  resizeHandleColumnIndex?: number;
121
121
  resizeHandleIncludeTooltip?: boolean;
122
+ isKeyboardResize?: boolean;
122
123
  // for table wrap/collapse
123
124
  isTableCollapsed?: boolean; // is the current table already in an expand?
124
125
  canCollapseTable?: boolean; // enabled/disabled state of collapse option
@@ -179,6 +180,16 @@ export type TablePluginAction =
179
180
  isInDanger?: boolean;
180
181
  };
181
182
  }
183
+ | {
184
+ type: 'START_KEYBOARD_COLUMN_RESIZE';
185
+ data: {
186
+ decorationSet: DecorationSet;
187
+ resizeHandleRowIndex: number;
188
+ resizeHandleColumnIndex: number;
189
+ resizeHandleIncludeTooltip: boolean;
190
+ isKeyboardResize?: boolean;
191
+ };
192
+ }
182
193
  | {
183
194
  type: 'ADD_RESIZE_HANDLE_DECORATIONS';
184
195
  data: {
@@ -186,6 +197,7 @@ export type TablePluginAction =
186
197
  resizeHandleRowIndex: number;
187
198
  resizeHandleColumnIndex: number;
188
199
  resizeHandleIncludeTooltip: boolean;
200
+ isKeyboardResize?: boolean;
189
201
  };
190
202
  }
191
203
  | {
@@ -201,6 +213,10 @@ export type TablePluginAction =
201
213
  type: 'REMOVE_RESIZE_HANDLE_DECORATIONS';
202
214
  data: { decorationSet: DecorationSet };
203
215
  }
216
+ | {
217
+ type: 'STOP_KEYBOARD_COLUMN_RESIZE';
218
+ data: { decorationSet: DecorationSet };
219
+ }
204
220
  | { type: 'CLEAR_HOVER_SELECTION'; data: { decorationSet: DecorationSet } }
205
221
  | { type: 'SHOW_RESIZE_HANDLE_LINE'; data: { decorationSet: DecorationSet } }
206
222
  | { type: 'HIDE_RESIZE_HANDLE_LINE'; data: { decorationSet: DecorationSet } }
@@ -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
  }