@atlaskit/editor-plugin-table 7.1.0 → 7.1.2

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 (88) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/event-handlers.js +4 -1
  3. package/dist/cjs/pm-plugins/drag-and-drop/commands-with-analytics.js +9 -9
  4. package/dist/cjs/pm-plugins/drag-and-drop/commands.js +4 -11
  5. package/dist/cjs/pm-plugins/drag-and-drop/plugin.js +1 -4
  6. package/dist/cjs/pm-plugins/drag-and-drop/utils/monitor.js +0 -5
  7. package/dist/cjs/types.js +1 -0
  8. package/dist/cjs/ui/DragHandle/index.js +27 -9
  9. package/dist/cjs/ui/FloatingContextualMenu/ContextualMenu.js +1 -1
  10. package/dist/cjs/ui/FloatingContextualMenu/index.js +4 -3
  11. package/dist/cjs/ui/FloatingContextualMenu/styles.js +3 -1
  12. package/dist/cjs/ui/TableFloatingColumnControls/ColumnControls/index.js +12 -4
  13. package/dist/cjs/ui/TableFloatingColumnControls/ColumnDropTargets/index.js +1 -7
  14. package/dist/cjs/ui/TableFloatingColumnControls/index.js +0 -2
  15. package/dist/cjs/ui/TableFloatingControls/RowControls/DragControls.js +10 -2
  16. package/dist/cjs/ui/common-styles.js +2 -1
  17. package/dist/cjs/ui/consts.js +3 -3
  18. package/dist/cjs/ui/ui-styles.js +8 -8
  19. package/dist/cjs/utils/drag-menu.js +42 -29
  20. package/dist/es2019/event-handlers.js +3 -2
  21. package/dist/es2019/pm-plugins/drag-and-drop/commands-with-analytics.js +8 -8
  22. package/dist/es2019/pm-plugins/drag-and-drop/commands.js +5 -10
  23. package/dist/es2019/pm-plugins/drag-and-drop/plugin.js +1 -4
  24. package/dist/es2019/pm-plugins/drag-and-drop/utils/monitor.js +0 -5
  25. package/dist/es2019/types.js +1 -0
  26. package/dist/es2019/ui/DragHandle/index.js +26 -8
  27. package/dist/es2019/ui/FloatingContextualMenu/ContextualMenu.js +2 -2
  28. package/dist/es2019/ui/FloatingContextualMenu/index.js +5 -4
  29. package/dist/es2019/ui/FloatingContextualMenu/styles.js +3 -3
  30. package/dist/es2019/ui/TableFloatingColumnControls/ColumnControls/index.js +10 -4
  31. package/dist/es2019/ui/TableFloatingColumnControls/ColumnDropTargets/index.js +1 -7
  32. package/dist/es2019/ui/TableFloatingColumnControls/index.js +0 -2
  33. package/dist/es2019/ui/TableFloatingControls/RowControls/DragControls.js +8 -2
  34. package/dist/es2019/ui/common-styles.js +24 -5
  35. package/dist/es2019/ui/consts.js +2 -2
  36. package/dist/es2019/ui/ui-styles.js +8 -8
  37. package/dist/es2019/utils/drag-menu.js +29 -24
  38. package/dist/esm/event-handlers.js +5 -2
  39. package/dist/esm/pm-plugins/drag-and-drop/commands-with-analytics.js +9 -9
  40. package/dist/esm/pm-plugins/drag-and-drop/commands.js +5 -12
  41. package/dist/esm/pm-plugins/drag-and-drop/plugin.js +1 -4
  42. package/dist/esm/pm-plugins/drag-and-drop/utils/monitor.js +0 -5
  43. package/dist/esm/types.js +1 -0
  44. package/dist/esm/ui/DragHandle/index.js +27 -9
  45. package/dist/esm/ui/FloatingContextualMenu/ContextualMenu.js +2 -2
  46. package/dist/esm/ui/FloatingContextualMenu/index.js +5 -4
  47. package/dist/esm/ui/FloatingContextualMenu/styles.js +4 -2
  48. package/dist/esm/ui/TableFloatingColumnControls/ColumnControls/index.js +12 -4
  49. package/dist/esm/ui/TableFloatingColumnControls/ColumnDropTargets/index.js +1 -7
  50. package/dist/esm/ui/TableFloatingColumnControls/index.js +0 -2
  51. package/dist/esm/ui/TableFloatingControls/RowControls/DragControls.js +10 -2
  52. package/dist/esm/ui/common-styles.js +2 -1
  53. package/dist/esm/ui/consts.js +2 -2
  54. package/dist/esm/ui/ui-styles.js +8 -8
  55. package/dist/esm/utils/drag-menu.js +41 -28
  56. package/dist/types/types.d.ts +1 -0
  57. package/dist/types/ui/FloatingContextualMenu/styles.d.ts +1 -1
  58. package/dist/types/ui/TableFloatingColumnControls/ColumnDropTargets/index.d.ts +0 -2
  59. package/dist/types/ui/consts.d.ts +2 -1
  60. package/dist/types/ui/ui-styles.d.ts +2 -2
  61. package/dist/types-ts4.5/types.d.ts +1 -0
  62. package/dist/types-ts4.5/ui/FloatingContextualMenu/styles.d.ts +1 -1
  63. package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnDropTargets/index.d.ts +0 -2
  64. package/dist/types-ts4.5/ui/consts.d.ts +2 -1
  65. package/dist/types-ts4.5/ui/ui-styles.d.ts +2 -2
  66. package/package.json +3 -5
  67. package/src/__tests__/unit/event-handlers.ts +3 -17
  68. package/src/__tests__/unit/nodeviews/TableComponent.tsx +1 -1
  69. package/src/__tests__/unit/pm-plugins/decorations/column-controls.ts +46 -17
  70. package/src/event-handlers.ts +14 -2
  71. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +11 -8
  72. package/src/pm-plugins/drag-and-drop/commands.ts +5 -33
  73. package/src/pm-plugins/drag-and-drop/plugin.ts +0 -3
  74. package/src/pm-plugins/drag-and-drop/utils/monitor.ts +0 -5
  75. package/src/types.ts +1 -0
  76. package/src/ui/DragHandle/index.tsx +33 -14
  77. package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +9 -2
  78. package/src/ui/FloatingContextualMenu/index.tsx +10 -3
  79. package/src/ui/FloatingContextualMenu/styles.ts +10 -3
  80. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +21 -5
  81. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +1 -13
  82. package/src/ui/TableFloatingColumnControls/index.tsx +0 -2
  83. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +22 -8
  84. package/src/ui/common-styles.ts +20 -4
  85. package/src/ui/consts.ts +2 -6
  86. package/src/ui/ui-styles.ts +12 -8
  87. package/src/utils/drag-menu.ts +48 -32
  88. package/tsconfig.json +273 -0
@@ -7,11 +7,11 @@ import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
7
7
  import type { Command, DocBuilder } from '@atlaskit/editor-common/types';
8
8
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
9
9
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
10
- import { selectTableClosestToPos } from '@atlaskit/editor-tables/src/utils/select-nodes';
11
10
  import {
12
11
  findTable,
13
12
  findTableClosestToPos,
14
13
  selectTable,
14
+ selectTableClosestToPos,
15
15
  } from '@atlaskit/editor-tables/utils';
16
16
  // eslint-disable-next-line import/no-extraneous-dependencies -- Removed import for fixing circular dependencies
17
17
  import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
@@ -1,7 +1,19 @@
1
+ import type { DocBuilder } from '@atlaskit/editor-common/types';
2
+ import type { LightEditorPlugin } from '@atlaskit/editor-core/src/create-editor/get-plugins';
3
+ import { analyticsPlugin } from '@atlaskit/editor-plugin-analytics';
4
+ import { contentInsertionPlugin } from '@atlaskit/editor-plugin-content-insertion';
5
+ import { decorationsPlugin } from '@atlaskit/editor-plugin-decorations';
6
+ import { featureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
7
+ import { gridPlugin } from '@atlaskit/editor-plugin-grid';
8
+ import { guidelinePlugin } from '@atlaskit/editor-plugin-guideline';
9
+ import { selectionPlugin } from '@atlaskit/editor-plugin-selection';
10
+ import { widthPlugin } from '@atlaskit/editor-plugin-width';
1
11
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
2
12
  // eslint-disable-next-line import/no-extraneous-dependencies -- Removed import for fixing circular dependencies
3
- import { createEditorState } from '@atlaskit/editor-test-helpers/create-editor-state';
4
- // eslint-disable-next-line import/no-extraneous-dependencies -- Removed import for fixing circular dependencies
13
+ import {
14
+ createProsemirrorEditorFactory,
15
+ Preset,
16
+ } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
5
17
  import {
6
18
  doc,
7
19
  table,
@@ -9,27 +21,43 @@ import {
9
21
  tdEmpty,
10
22
  tr,
11
23
  } from '@atlaskit/editor-test-helpers/doc-builder';
12
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
13
24
 
25
+ import tablePlugin from '../../../../plugin';
14
26
  import { buildColumnControlsDecorations } from '../../../../pm-plugins/decorations/utils';
27
+ import { pluginKey } from '../../../../pm-plugins/plugin-key';
15
28
  import { TableDecorations } from '../../../../types';
16
29
 
17
- // Mock Feature flags instead of using ffTest because we don't use the feature flag directly
18
- jest.mock('@atlaskit/platform-feature-flags', () => ({
19
- getBooleanFF: jest.fn().mockImplementation(() => false),
20
- }));
21
-
22
- afterEach(() => {
23
- (getBooleanFF as jest.Mock).mockReset();
24
- });
25
-
26
30
  describe('tables: column controls decorations', () => {
31
+ const createEditor = createProsemirrorEditorFactory();
32
+ const editor = (doc: DocBuilder, isDragAndDropEnabled = false) =>
33
+ createEditor({
34
+ doc,
35
+ attachTo: document.body,
36
+ featureFlags: {
37
+ tableDragAndDrop: isDragAndDropEnabled,
38
+ },
39
+ preset: new Preset<LightEditorPlugin>()
40
+ .add([featureFlagsPlugin, {}])
41
+ .add([analyticsPlugin, {}])
42
+ .add(contentInsertionPlugin)
43
+ .add(decorationsPlugin)
44
+ .add(widthPlugin)
45
+ .add(guidelinePlugin)
46
+ .add(gridPlugin)
47
+ .add(selectionPlugin)
48
+ .add([
49
+ tablePlugin,
50
+ {
51
+ tableOptions: { advanced: true },
52
+ },
53
+ ]),
54
+ pluginKey,
55
+ });
56
+
27
57
  it(`should return an empty decorationSet ${TableDecorations.COLUMN_CONTROLS_DECORATIONS} type when drag and drop is enabled`, () => {
28
- (getBooleanFF as jest.Mock).mockImplementation(
29
- (name) => name === 'platform.editor.table.drag-and-drop',
30
- );
31
58
  const decorationKey = TableDecorations.COLUMN_CONTROLS_DECORATIONS;
32
- const state = createEditorState(doc(table()(tr(tdCursor, tdEmpty))));
59
+ const editorInstance = editor(doc(table()(tr(tdCursor, tdEmpty))), true);
60
+ const state = editorInstance.editorView.state;
33
61
  const nextDecorationSet = buildColumnControlsDecorations({
34
62
  decorationSet: DecorationSet.empty,
35
63
  tr: state.tr,
@@ -47,7 +75,8 @@ describe('tables: column controls decorations', () => {
47
75
 
48
76
  it(`should return an empty decorationSet ${TableDecorations.COLUMN_CONTROLS_DECORATIONS} type when drag and drop is disabled`, () => {
49
77
  const decorationKey = TableDecorations.COLUMN_CONTROLS_DECORATIONS;
50
- const state = createEditorState(doc(table()(tr(tdCursor, tdEmpty))));
78
+ const editorInstance = editor(doc(table()(tr(tdCursor, tdEmpty))), false);
79
+ const state = editorInstance.editorView.state;
51
80
  const nextDecorationSet = buildColumnControlsDecorations({
52
81
  decorationSet: DecorationSet.empty,
53
82
  tr: state.tr,
@@ -47,7 +47,10 @@ import { getPluginState } from './pm-plugins/plugin-factory';
47
47
  import { getPluginState as getResizePluginState } from './pm-plugins/table-resizing/plugin-factory';
48
48
  import { deleteColumns, deleteRows } from './transforms';
49
49
  import type { ElementContentRects } from './types';
50
- import { RESIZE_HANDLE_AREA_DECORATION_GAP } from './types';
50
+ import {
51
+ TableCssClassName as ClassName,
52
+ RESIZE_HANDLE_AREA_DECORATION_GAP,
53
+ } from './types';
51
54
  import {
52
55
  convertHTMLCellIndexToColumnIndex,
53
56
  getColumnIndexMappedToColumnIndexInFirstRow,
@@ -91,6 +94,14 @@ const isFocusingDragHandles = (event: Event) =>
91
94
  event.relatedTarget.closest('button') &&
92
95
  event.relatedTarget.getAttribute('draggable') === 'true';
93
96
 
97
+ const isFocusingDragHandlesClickableZone = (event: Event) =>
98
+ event instanceof FocusEvent &&
99
+ event.relatedTarget instanceof HTMLElement &&
100
+ event.relatedTarget.closest('button') &&
101
+ event.relatedTarget.classList.contains(
102
+ ClassName.DRAG_HANDLE_BUTTON_CLICKABLE_ZONE,
103
+ );
104
+
94
105
  export const handleBlur = (view: EditorView, event: Event): boolean => {
95
106
  const { state, dispatch } = view;
96
107
  // IE version check for ED-4665
@@ -100,7 +111,8 @@ export const handleBlur = (view: EditorView, event: Event): boolean => {
100
111
  !isFocusingCalendar(event) &&
101
112
  !isFocusingModal(event) &&
102
113
  !isFocusingFloatingToolbar(event) &&
103
- !isFocusingDragHandles(event)
114
+ !isFocusingDragHandles(event) &&
115
+ !isFocusingDragHandlesClickableZone(event)
104
116
  ) {
105
117
  setEditorFocus(false)(state, dispatch);
106
118
  }
@@ -79,6 +79,7 @@ export const moveSourceWithAnalytics =
79
79
  tr?: Transaction,
80
80
  ) => {
81
81
  return withEditorAnalyticsAPI(({ selection }: EditorState) => {
82
+ const direction = sourceIndexes[0] > targetIndex ? -1 : 1;
82
83
  const { totalRowCount, totalColumnCount } =
83
84
  getSelectedTableInfo(selection);
84
85
  return {
@@ -93,7 +94,9 @@ export const moveSourceWithAnalytics =
93
94
  count: sourceIndexes.length,
94
95
  // This identifies the total amount of row/cols the move operation covered. The distance covered should be a representaion
95
96
  // of the minimum distance. This will account for large selection being moved causing a large distance travelled value.
96
- distance: Math.min(...sourceIndexes.map((v) => targetIndex - v)),
97
+ distance:
98
+ Math.min(...sourceIndexes.map((v) => Math.abs(targetIndex - v))) *
99
+ direction,
97
100
  // If a drop doesn't actually change anything then we're going to mark the event as cancelled.
98
101
  status: sourceIndexes.includes(targetIndex)
99
102
  ? TABLE_STATUS.CANCELLED
@@ -130,15 +133,15 @@ export const moveSourceWithAnalyticsViaShortcut =
130
133
  ? getSelectedRowIndexes(selectionRect)
131
134
  : getSelectedColumnIndexes(selectionRect);
132
135
 
133
- // FIXME: We can move if only one row/column selected
134
- if (selectedIndexes.length === 0 || selectedIndexes.length > 1) {
136
+ if (selectedIndexes.length === 0) {
135
137
  return false;
136
138
  }
137
139
 
138
- const sourceIndex = selectedIndexes[0];
140
+ // const sourceIndex = selectedIndexes[0];
139
141
  // we can move only by one row/column
140
142
  // 'direction' can only be 1 (for right or down) or -1 (for left or up)
141
- const targetIndex = sourceIndex + direction;
143
+ const targetIndex =
144
+ Math[direction < 0 ? 'min' : 'max'](...selectedIndexes) + direction;
142
145
 
143
146
  // We can move only if targetIndex is a positive number and is not higher than the total number of rows/columns.
144
147
  const { totalRowCount, totalColumnCount } = getSelectedTableInfo(selection);
@@ -155,8 +158,8 @@ export const moveSourceWithAnalyticsViaShortcut =
155
158
 
156
159
  // We can move only if there are no merged cells in the source or target row/column
157
160
  const hasMergedCellsInSource = isRow
158
- ? hasMergedCellsInRow(sourceIndex)(selection)
159
- : hasMergedCellsInColumn(sourceIndex)(selection);
161
+ ? hasMergedCellsInRow(selectedIndexes)(selection)
162
+ : hasMergedCellsInColumn(selectedIndexes)(selection);
160
163
  if (hasMergedCellsInSource) {
161
164
  return false;
162
165
  }
@@ -171,7 +174,7 @@ export const moveSourceWithAnalyticsViaShortcut =
171
174
  return moveSourceWithAnalytics(editorAnalyticsAPI)(
172
175
  INPUT_METHOD.SHORTCUT,
173
176
  sourceType,
174
- [sourceIndex],
177
+ selectedIndexes,
175
178
  targetIndex,
176
179
  )(state, dispatch);
177
180
  };
@@ -2,15 +2,9 @@ import type {
2
2
  EditorState,
3
3
  Transaction,
4
4
  } from '@atlaskit/editor-prosemirror/state';
5
- import { TextSelection } from '@atlaskit/editor-prosemirror/state';
6
5
  import type { Decoration } from '@atlaskit/editor-prosemirror/view';
7
6
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
- import {
9
- moveColumn,
10
- moveRow,
11
- selectColumn,
12
- selectRow,
13
- } from '@atlaskit/editor-tables/utils';
7
+ import { moveColumn, moveRow } from '@atlaskit/editor-tables/utils';
14
8
 
15
9
  import type { DraggableType, TableDirection } from '../../types';
16
10
  import { TableDecorations } from '../../types';
@@ -19,7 +13,6 @@ import {
19
13
  createRowInsertLine,
20
14
  updateDecorations,
21
15
  } from '../../utils';
22
- import { combineTransforms } from '../../utils/transforms';
23
16
 
24
17
  import { DragAndDropActionType } from './actions';
25
18
  import { DropTargetType } from './consts';
@@ -118,31 +111,10 @@ export const moveSource = (
118
111
  if (sourceIndexes.includes(targetIndex)) {
119
112
  return nextTr.setMeta('addToHistory', false);
120
113
  }
121
-
122
- const anchor = nextTr.selection.anchor;
123
- const selectStartOfTable = (newTr: Transaction) =>
124
- newTr.setSelection(TextSelection.create(newTr.doc, anchor));
125
-
126
- const isTableRow = sourceType === 'table-row';
127
- if (isTableRow) {
128
- return combineTransforms(
129
- [
130
- moveRow(state, sourceIndexes, targetIndex),
131
- selectStartOfTable,
132
- selectRow(targetIndex),
133
- ],
134
- nextTr,
135
- );
136
- }
137
-
138
- return combineTransforms(
139
- [
140
- moveColumn(state, sourceIndexes, targetIndex),
141
- selectStartOfTable,
142
- selectColumn(targetIndex),
143
- ],
144
- nextTr,
145
- );
114
+ const move = sourceType === 'table-row' ? moveRow : moveColumn;
115
+ return move(state, sourceIndexes, targetIndex, {
116
+ selectAfterMove: true,
117
+ })(nextTr);
146
118
  },
147
119
  );
148
120
 
@@ -82,9 +82,6 @@ const destroyFn = (editorView: EditorView, editorAnalyticsAPI: any) => {
82
82
  if (
83
83
  !indexes ||
84
84
  !localId ||
85
- // FIXME: We currently don't support DragNDrop of multiple elements. For now we will not bother to monitor drags
86
- // of more then 1 item.
87
- indexes.length !== 1 ||
88
85
  !(type === 'table-row' || type === 'table-column')
89
86
  ) {
90
87
  return false;
@@ -45,11 +45,6 @@ export const getDraggableDataFromEvent = ({
45
45
  return undefined;
46
46
  }
47
47
 
48
- // FIXME: currently we only support a single row/col index being moved, remove this clause when this is no longer the case.
49
- if (sourceIndexes.length > 1) {
50
- return undefined;
51
- }
52
-
53
48
  const targetClosestEdge =
54
49
  extractClosestEdge(destination.data) ??
55
50
  ((targetType === 'table-row' ? 'top' : 'left') as Edge);
package/src/types.ts CHANGED
@@ -330,6 +330,7 @@ export const TableCssClassName = {
330
330
  DRAG_COLUMN_CONTROLS_INNER: `${tablePrefixSelector}-col-controls__inner`,
331
331
 
332
332
  DRAG_HANDLE_BUTTON_CONTAINER: `${tablePrefixSelector}-drag-handle-button-container`,
333
+ DRAG_HANDLE_BUTTON_CLICKABLE_ZONE: `${tablePrefixSelector}-drag-handle-button-clickable-zone`,
333
334
 
334
335
  DRAG_CORNER_BUTTON: `${tablePrefixSelector}-drag-corner-button`,
335
336
  DRAG_CORNER_BUTTON_INNER: `${tablePrefixSelector}-drag-corner-button-inner`,
@@ -11,11 +11,13 @@ import { browser } from '@atlaskit/editor-common/utils';
11
11
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
12
12
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
13
13
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
14
+ import { token } from '@atlaskit/tokens';
14
15
 
15
16
  import { getPluginState } from '../../pm-plugins/plugin-factory';
16
17
  import type { TableDirection } from '../../types';
17
18
  import { TableCssClassName as ClassName } from '../../types';
18
19
  import { hasMergedCellsInColumn, hasMergedCellsInRow } from '../../utils';
20
+ import { dragTableInsertColumnButtonSize } from '../consts';
19
21
  import { DragPreview } from '../DragPreview';
20
22
 
21
23
  import { HandleIconComponent } from './HandleIconComponent';
@@ -64,17 +66,18 @@ const DragHandleComponent = ({
64
66
  const { hoveredColumns, hoveredRows } = getPluginState(editorView.state);
65
67
 
66
68
  const { selection } = editorView.state;
69
+ const isRow = direction === 'row';
70
+ const isColumn = direction === 'column';
67
71
 
68
- const isRowHandleHovered = direction === 'row' && hoveredRows.length > 0;
69
- const isColumnHandleHovered =
70
- direction === 'column' && hoveredColumns.length > 0;
72
+ const isRowHandleHovered = isRow && hoveredRows.length > 0;
73
+ const isColumnHandleHovered = isColumn && hoveredColumns.length > 0;
71
74
 
72
75
  const hasMergedCells = useMemo(
73
76
  () =>
74
- direction === 'row'
77
+ isRow
75
78
  ? hasMergedCellsInRow(indexes[0])(selection)
76
79
  : hasMergedCellsInColumn(indexes[0])(selection),
77
- [indexes, direction, selection],
80
+ [indexes, isRow, selection],
78
81
  );
79
82
 
80
83
  const handleIconProps = {
@@ -113,7 +116,7 @@ const DragHandleComponent = ({
113
116
  // be generated.
114
117
  container.style.left = `-${rect.width - 0.0001}px`;
115
118
  }
116
- if (direction === 'row') {
119
+ if (isRow) {
117
120
  return { x: 12, y: rect.height / 2 };
118
121
  } else {
119
122
  return { x: rect.width / 2 + 4, y: 12 };
@@ -132,18 +135,35 @@ const DragHandleComponent = ({
132
135
  tableLocalId,
133
136
  direction,
134
137
  indexes,
138
+ isRow,
135
139
  editorView.state.selection,
136
140
  hasMergedCells,
137
141
  canDrag,
138
142
  ]);
139
143
 
140
- const showDragMenuAnchorId =
141
- direction === 'row'
142
- ? 'drag-handle-button-row'
143
- : 'drag-handle-button-column';
144
+ const showDragMenuAnchorId = isRow
145
+ ? 'drag-handle-button-row'
146
+ : 'drag-handle-button-column';
144
147
 
145
148
  return (
146
149
  <>
150
+ <button
151
+ className={ClassName.DRAG_HANDLE_BUTTON_CLICKABLE_ZONE}
152
+ data-testid="table-drag-handle-clickable-zone-button"
153
+ style={{
154
+ height: isRow
155
+ ? `calc(100% - ${dragTableInsertColumnButtonSize}px)`
156
+ : `${token('space.200', '16px')}`, // 16px here because it's the size of drag handle button's large side
157
+ width: isRow
158
+ ? `${token('space.200', '16px')}` // 16px here because it's the size of drag handle button's large side
159
+ : `calc(100% - ${dragTableInsertColumnButtonSize}px)`,
160
+ left: isRow ? '3px' : undefined,
161
+ bottom: isColumn ? '0' : undefined,
162
+ alignSelf: isColumn ? 'none' : 'center',
163
+ zIndex: isColumn ? '-1' : 'auto',
164
+ }}
165
+ onClick={onClick}
166
+ />
147
167
  <button
148
168
  id={isDragMenuTarget ? showDragMenuAnchorId : undefined}
149
169
  className={classnames(
@@ -155,13 +175,12 @@ const DragHandleComponent = ({
155
175
  )}
156
176
  ref={dragHandleDivRef}
157
177
  style={{
158
- transform: direction === 'column' ? 'none' : 'rotate(90deg)',
178
+ transform: isColumn ? 'none' : 'rotate(90deg)',
179
+ alignSelf: isColumn ? 'none' : 'center',
159
180
  }}
160
181
  data-testid="table-drag-handle-button"
161
182
  aria-label={formatMessage(
162
- direction === 'row'
163
- ? messages.rowDragHandle
164
- : messages.columnDragHandle,
183
+ isRow ? messages.rowDragHandle : messages.columnDragHandle,
165
184
  )}
166
185
  onMouseOver={onMouseOver}
167
186
  onMouseOut={onMouseOut}
@@ -73,7 +73,10 @@ import {
73
73
  getSelectedColumnIndexes,
74
74
  getSelectedRowIndexes,
75
75
  } from '../../utils';
76
- import { contextualMenuDropdownWidth } from '../consts';
76
+ import {
77
+ contextualMenuDropdownWidth,
78
+ contextualMenuDropdownWidthDnD,
79
+ } from '../consts';
77
80
  import {
78
81
  AddColRightIcon,
79
82
  AddRowBelowIcon,
@@ -145,7 +148,11 @@ export class ContextualMenu extends Component<
145
148
  onMouseEnter={this.handleItemMouseEnter}
146
149
  onMouseLeave={this.handleItemMouseLeave}
147
150
  fitHeight={188}
148
- fitWidth={contextualMenuDropdownWidth}
151
+ fitWidth={
152
+ isDragAndDropEnabled
153
+ ? contextualMenuDropdownWidthDnD
154
+ : contextualMenuDropdownWidth
155
+ }
149
156
  boundariesElement={boundariesElement}
150
157
  offset={offset}
151
158
  section={
@@ -23,6 +23,7 @@ import { getPluginState } from '../../pm-plugins/plugin-factory';
23
23
  import type { PluginConfig } from '../../types';
24
24
  import {
25
25
  contextualMenuDropdownWidth,
26
+ contextualMenuDropdownWidthDnD,
26
27
  contextualMenuTriggerSize,
27
28
  } from '../consts';
28
29
 
@@ -53,7 +54,9 @@ const FloatingContextualMenu = ({
53
54
  getEditorContainerWidth,
54
55
  }: Props) => {
55
56
  // TargetCellPosition could be outdated: https://product-fabric.atlassian.net/browse/ED-8129
56
- const { targetCellPosition } = getPluginState(editorView.state);
57
+ const { targetCellPosition, isDragAndDropEnabled } = getPluginState(
58
+ editorView.state,
59
+ );
57
60
  if (
58
61
  !isOpen ||
59
62
  !targetCellPosition ||
@@ -89,7 +92,11 @@ const FloatingContextualMenu = ({
89
92
  boundariesElement={boundariesElement}
90
93
  scrollableElement={scrollableElement}
91
94
  fitHeight={188}
92
- fitWidth={contextualMenuDropdownWidth}
95
+ fitWidth={
96
+ isDragAndDropEnabled
97
+ ? contextualMenuDropdownWidthDnD
98
+ : contextualMenuDropdownWidth
99
+ }
93
100
  // z-index value below is to ensure that this menu is above other floating menu
94
101
  // in table, but below floating dialogs like typeaheads, pickers, etc.
95
102
  zIndex={
@@ -101,7 +108,7 @@ const FloatingContextualMenu = ({
101
108
  offset={[-7, 0]}
102
109
  stick={true}
103
110
  >
104
- <div css={tablePopupStyles}>
111
+ <div css={tablePopupStyles(isDragAndDropEnabled)}>
105
112
  <ContextualMenu
106
113
  editorView={editorView}
107
114
  offset={[contextualMenuTriggerSize / 2, -contextualMenuTriggerSize]}
@@ -5,7 +5,10 @@ import { N60A, N90 } from '@atlaskit/theme/colors';
5
5
  import { token } from '@atlaskit/tokens';
6
6
 
7
7
  import { TableCssClassName as ClassName } from '../../types';
8
- import { contextualMenuDropdownWidth } from '../consts';
8
+ import {
9
+ contextualMenuDropdownWidth,
10
+ contextualMenuDropdownWidthDnD,
11
+ } from '../consts';
9
12
 
10
13
  export const cellColourPreviewStyles = (selectedColor: string) => css`
11
14
  &::before {
@@ -20,7 +23,9 @@ export const elementBeforeIconStyles = css`
20
23
 
21
24
  // TODO Delete this comment after verifying space token -> previous value `padding: 8px`
22
25
  // TODO Delete this comment after verifying space token -> previous value `margin-left: 4px`
23
- export const tablePopupStyles = css`
26
+ export const tablePopupStyles = (
27
+ isDragAndDropEnabled: boolean | undefined,
28
+ ) => css`
24
29
  .${ClassName.CONTEXTUAL_SUBMENU} {
25
30
  border-radius: ${token('border.radius', '3px')};
26
31
  background: ${token('elevation.surface.overlay', 'white')};
@@ -31,7 +36,9 @@ export const tablePopupStyles = css`
31
36
  display: block;
32
37
  position: absolute;
33
38
  top: 0;
34
- left: ${contextualMenuDropdownWidth}px;
39
+ left: ${isDragAndDropEnabled
40
+ ? contextualMenuDropdownWidthDnD
41
+ : contextualMenuDropdownWidth}px;
35
42
  padding: ${token('space.100', '8px')};
36
43
 
37
44
  > div {
@@ -159,10 +159,17 @@ export const ColumnControls = ({
159
159
  }
160
160
  }, [editorView, tableActive]);
161
161
 
162
- const handleMouseUp = useCallback(() => {
163
- const { state, dispatch } = editorView;
164
- toggleDragMenu(undefined, 'column', colIndex)(state, dispatch);
165
- }, [editorView, colIndex]);
162
+ const handleMouseUp = useCallback(
163
+ (event) => {
164
+ const { state, dispatch } = editorView;
165
+ if (event.shiftKey) {
166
+ return;
167
+ }
168
+
169
+ toggleDragMenu(undefined, 'column', colIndex)(state, dispatch);
170
+ },
171
+ [editorView, colIndex],
172
+ );
166
173
 
167
174
  const colIndexes = useMemo(() => {
168
175
  return [colIndex!];
@@ -240,6 +247,13 @@ export const ColumnControls = ({
240
247
  : selectedColIndexes
241
248
  : colIndexes;
242
249
 
250
+ const previewWidth =
251
+ colWidths?.reduce<number>(
252
+ (sum, v, i) =>
253
+ sum + (v ?? tableCellMinWidth) * (indexes.includes(i) ? 1 : 0),
254
+ 0,
255
+ ) ?? tableCellMinWidth;
256
+
243
257
  return (
244
258
  <div
245
259
  key={type}
@@ -251,6 +265,8 @@ export const ColumnControls = ({
251
265
  height: 'fit-content',
252
266
  placeSelf: 'center',
253
267
  zIndex: 99,
268
+ width: '100%',
269
+ position: 'relative',
254
270
  }}
255
271
  data-column-control-index={hoveredCell.colIndex}
256
272
  data-testid={`table-floating-column-${
@@ -263,7 +279,7 @@ export const ColumnControls = ({
263
279
  tableLocalId={localId || ''}
264
280
  indexes={indexes}
265
281
  forceDefaultHandle={isHover ? false : isColumnsSelected}
266
- previewWidth={colWidths?.[colIndex!] ?? tableCellMinWidth}
282
+ previewWidth={previewWidth}
267
283
  previewHeight={previewHeight}
268
284
  appearance={
269
285
  isSelecting ? currentSelectionAppearance : hoveredAppearance
@@ -6,33 +6,21 @@ import { ColumnDropTarget } from './ColumnDropTarget';
6
6
 
7
7
  export interface Props {
8
8
  tableRef: HTMLTableElement;
9
- stickyTop?: number;
10
9
  tableHeight?: number;
11
10
  localId?: string;
12
- rowHeights?: number[];
13
11
  colWidths?: (number | undefined)[];
14
12
  }
15
13
 
16
14
  export const ColumnDropTargets: React.FC<Props> = ({
17
15
  tableRef,
18
16
  tableHeight,
19
- stickyTop,
20
17
  localId,
21
- rowHeights,
22
18
  colWidths,
23
19
  }) => {
24
20
  if (!tableRef) {
25
21
  return null;
26
22
  }
27
23
 
28
- const firstRow = tableRef.querySelector('tr');
29
- const hasHeaderRow = firstRow
30
- ? firstRow.getAttribute('data-header-row')
31
- : false;
32
-
33
- const marginTop =
34
- hasHeaderRow && stickyTop !== undefined ? rowHeights?.[0] ?? 0 : 0;
35
-
36
24
  return (
37
25
  <div
38
26
  className={ClassName.DRAG_COLUMN_DROP_TARGET_CONTROLS}
@@ -50,7 +38,7 @@ export const ColumnDropTargets: React.FC<Props> = ({
50
38
  localId={localId}
51
39
  width={width}
52
40
  height={tableHeight}
53
- marginTop={marginTop}
41
+ marginTop={0}
54
42
  />
55
43
  );
56
44
  })}
@@ -165,10 +165,8 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
165
165
  {isDragging && (
166
166
  <ColumnDropTargets
167
167
  tableRef={tableRef}
168
- stickyTop={tableActive ? stickyTop : undefined}
169
168
  tableHeight={tableRect.height}
170
169
  localId={currentNodeLocalId}
171
- rowHeights={rowHeights}
172
170
  colWidths={colWidths}
173
171
  />
174
172
  )}
@@ -113,13 +113,20 @@ const DragControlsComponent = ({
113
113
  });
114
114
  }, [editorView]);
115
115
 
116
- const onMouseUp = useCallback(() => {
117
- toggleDragMenu(
118
- undefined,
119
- 'row',
120
- hoveredCell?.rowIndex,
121
- )(editorView.state, editorView.dispatch);
122
- }, [editorView, hoveredCell?.rowIndex]);
116
+ const onMouseUp = useCallback(
117
+ (event) => {
118
+ if (event.shiftKey) {
119
+ return;
120
+ }
121
+
122
+ toggleDragMenu(
123
+ undefined,
124
+ 'row',
125
+ hoveredCell?.rowIndex,
126
+ )(editorView.state, editorView.dispatch);
127
+ },
128
+ [editorView, hoveredCell?.rowIndex],
129
+ );
123
130
 
124
131
  const rowIndex = hoveredCell?.rowIndex;
125
132
 
@@ -228,6 +235,11 @@ const DragControlsComponent = ({
228
235
  : selectedRowIndexes
229
236
  : rowIndexes;
230
237
 
238
+ const previewHeight = rowHeights.reduce(
239
+ (sum, v, i) => sum + v * (indexes.includes(i) ? 1 : 0),
240
+ 0,
241
+ );
242
+
231
243
  return (
232
244
  <div
233
245
  key={type}
@@ -235,7 +247,9 @@ const DragControlsComponent = ({
235
247
  gridRow: isSelecting ? selectedRowPosition : gridRowPosition,
236
248
  gridColumn: '2',
237
249
  // DragHandle uses `transform: rotate(90)`, which doesn't affect its parent (this div) causing the width of this element to be the true height of the drag handle
250
+ display: 'flex',
238
251
  width: '9px',
252
+ height: '100%',
239
253
  position: 'relative',
240
254
  right: '-0.5px',
241
255
  }}
@@ -250,7 +264,7 @@ const DragControlsComponent = ({
250
264
  indexes={indexes}
251
265
  forceDefaultHandle={isHover ? false : isRowsSelected}
252
266
  previewWidth={tableWidth}
253
- previewHeight={rowHeights[rowIndex!]}
267
+ previewHeight={previewHeight}
254
268
  appearance={
255
269
  isSelecting ? currentSelectionAppearance : hoveredAppearance
256
270
  }