@atlaskit/editor-plugin-table 5.3.13 → 5.3.14

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 (95) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/plugins/table/event-handlers.js +6 -3
  3. package/dist/cjs/plugins/table/index.js +4 -3
  4. package/dist/cjs/plugins/table/pm-plugins/decorations/plugin.js +3 -7
  5. package/dist/cjs/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  6. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/plugin.js +11 -0
  7. package/dist/cjs/plugins/table/types.js +9 -2
  8. package/dist/cjs/plugins/table/ui/FloatingDragMenu/index.js +5 -3
  9. package/dist/cjs/plugins/table/ui/FloatingInsertButton/InsertButton.js +57 -9
  10. package/dist/cjs/plugins/table/ui/FloatingInsertButton/getPopupOptions.js +9 -7
  11. package/dist/cjs/plugins/table/ui/FloatingInsertButton/index.js +13 -4
  12. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +44 -5
  13. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/index.js +6 -4
  14. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +35 -13
  15. package/dist/cjs/plugins/table/ui/TableFloatingControls/index.js +2 -0
  16. package/dist/cjs/plugins/table/ui/common-styles.js +1 -1
  17. package/dist/cjs/plugins/table/ui/ui-styles.js +27 -24
  18. package/dist/cjs/plugins/table/utils/dom.js +12 -4
  19. package/dist/cjs/plugins/table/utils/index.js +12 -0
  20. package/dist/es2019/plugins/table/event-handlers.js +5 -4
  21. package/dist/es2019/plugins/table/index.js +4 -3
  22. package/dist/es2019/plugins/table/pm-plugins/decorations/plugin.js +3 -7
  23. package/dist/es2019/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  24. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/plugin.js +12 -0
  25. package/dist/es2019/plugins/table/types.js +9 -2
  26. package/dist/es2019/plugins/table/ui/FloatingDragMenu/index.js +5 -3
  27. package/dist/es2019/plugins/table/ui/FloatingInsertButton/InsertButton.js +58 -7
  28. package/dist/es2019/plugins/table/ui/FloatingInsertButton/getPopupOptions.js +9 -7
  29. package/dist/es2019/plugins/table/ui/FloatingInsertButton/index.js +10 -4
  30. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +46 -6
  31. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/index.js +7 -5
  32. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +35 -14
  33. package/dist/es2019/plugins/table/ui/TableFloatingControls/index.js +2 -0
  34. package/dist/es2019/plugins/table/ui/common-styles.js +51 -3
  35. package/dist/es2019/plugins/table/ui/ui-styles.js +23 -1
  36. package/dist/es2019/plugins/table/utils/dom.js +5 -1
  37. package/dist/es2019/plugins/table/utils/index.js +1 -1
  38. package/dist/esm/plugins/table/event-handlers.js +7 -4
  39. package/dist/esm/plugins/table/index.js +4 -3
  40. package/dist/esm/plugins/table/pm-plugins/decorations/plugin.js +3 -7
  41. package/dist/esm/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  42. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/plugin.js +11 -0
  43. package/dist/esm/plugins/table/types.js +9 -2
  44. package/dist/esm/plugins/table/ui/FloatingDragMenu/index.js +5 -3
  45. package/dist/esm/plugins/table/ui/FloatingInsertButton/InsertButton.js +56 -8
  46. package/dist/esm/plugins/table/ui/FloatingInsertButton/getPopupOptions.js +9 -7
  47. package/dist/esm/plugins/table/ui/FloatingInsertButton/index.js +10 -4
  48. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +45 -6
  49. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/index.js +7 -5
  50. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +36 -14
  51. package/dist/esm/plugins/table/ui/TableFloatingControls/index.js +2 -0
  52. package/dist/esm/plugins/table/ui/common-styles.js +2 -2
  53. package/dist/esm/plugins/table/ui/ui-styles.js +26 -23
  54. package/dist/esm/plugins/table/utils/dom.js +11 -3
  55. package/dist/esm/plugins/table/utils/index.js +1 -1
  56. package/dist/types/plugins/table/types.d.ts +9 -2
  57. package/dist/types/plugins/table/ui/FloatingInsertButton/InsertButton.d.ts +5 -1
  58. package/dist/types/plugins/table/ui/FloatingInsertButton/getPopupOptions.d.ts +1 -1
  59. package/dist/types/plugins/table/ui/FloatingInsertButton/index.d.ts +1 -0
  60. package/dist/types/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -1
  61. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +2 -0
  62. package/dist/types/plugins/table/ui/ui-styles.d.ts +1 -0
  63. package/dist/types/plugins/table/utils/dom.d.ts +4 -1
  64. package/dist/types/plugins/table/utils/index.d.ts +1 -1
  65. package/dist/types-ts4.5/plugins/table/types.d.ts +9 -2
  66. package/dist/types-ts4.5/plugins/table/ui/FloatingInsertButton/InsertButton.d.ts +5 -1
  67. package/dist/types-ts4.5/plugins/table/ui/FloatingInsertButton/getPopupOptions.d.ts +1 -1
  68. package/dist/types-ts4.5/plugins/table/ui/FloatingInsertButton/index.d.ts +1 -0
  69. package/dist/types-ts4.5/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -1
  70. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +2 -0
  71. package/dist/types-ts4.5/plugins/table/ui/ui-styles.d.ts +1 -0
  72. package/dist/types-ts4.5/plugins/table/utils/dom.d.ts +4 -1
  73. package/dist/types-ts4.5/plugins/table/utils/index.d.ts +1 -1
  74. package/package.json +2 -1
  75. package/src/__tests__/unit/pm-plugins/decorations/plugin.ts +40 -194
  76. package/src/__tests__/unit/ui/RowDragControls.tsx +9 -11
  77. package/src/plugins/table/event-handlers.ts +15 -3
  78. package/src/plugins/table/index.tsx +3 -2
  79. package/src/plugins/table/pm-plugins/decorations/plugin.ts +2 -9
  80. package/src/plugins/table/pm-plugins/decorations/utils/column-controls.ts +1 -3
  81. package/src/plugins/table/pm-plugins/drag-and-drop/plugin.ts +9 -0
  82. package/src/plugins/table/types.ts +12 -2
  83. package/src/plugins/table/ui/FloatingDragMenu/index.tsx +10 -3
  84. package/src/plugins/table/ui/FloatingInsertButton/InsertButton.tsx +82 -8
  85. package/src/plugins/table/ui/FloatingInsertButton/getPopupOptions.ts +28 -5
  86. package/src/plugins/table/ui/FloatingInsertButton/index.tsx +19 -7
  87. package/src/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.tsx +47 -3
  88. package/src/plugins/table/ui/TableFloatingColumnControls/index.tsx +11 -4
  89. package/src/plugins/table/ui/TableFloatingControls/RowControls/DragControls.tsx +49 -18
  90. package/src/plugins/table/ui/TableFloatingControls/index.tsx +2 -0
  91. package/src/plugins/table/ui/common-styles.ts +57 -2
  92. package/src/plugins/table/ui/ui-styles.ts +27 -1
  93. package/src/plugins/table/utils/dom.ts +11 -4
  94. package/src/plugins/table/utils/index.ts +2 -0
  95. package/tsconfig.app.json +3 -0
@@ -55,6 +55,8 @@ import {
55
55
  isCell,
56
56
  isColumnControlsDecorations,
57
57
  isCornerButton,
58
+ isDragColumnFloatingInsertDot,
59
+ isDragRowFloatingInsertDot,
58
60
  isInsertRowButton,
59
61
  isResizeHandleDecoration,
60
62
  isRowControlsButton,
@@ -78,6 +80,12 @@ const isFocusingFloatingToolbar = (event: Event) =>
78
80
  event.relatedTarget instanceof HTMLElement &&
79
81
  event.relatedTarget.closest('[role="toolbar"]');
80
82
 
83
+ const isFocusingDragHandles = (event: Event) =>
84
+ event instanceof FocusEvent &&
85
+ event.relatedTarget instanceof HTMLElement &&
86
+ event.relatedTarget.closest('button') &&
87
+ event.relatedTarget.getAttribute('draggable') === 'true';
88
+
81
89
  export const handleBlur = (view: EditorView, event: Event): boolean => {
82
90
  const { state, dispatch } = view;
83
91
  // IE version check for ED-4665
@@ -86,7 +94,8 @@ export const handleBlur = (view: EditorView, event: Event): boolean => {
86
94
  browser.ie_version !== 11 &&
87
95
  !isFocusingCalendar(event) &&
88
96
  !isFocusingModal(event) &&
89
- !isFocusingFloatingToolbar(event)
97
+ !isFocusingFloatingToolbar(event) &&
98
+ !isFocusingDragHandles(event)
90
99
  ) {
91
100
  setEditorFocus(false)(state, dispatch);
92
101
  }
@@ -312,7 +321,10 @@ export const handleMouseMove = (
312
321
  }
313
322
  const element = event.target;
314
323
 
315
- if (isColumnControlsDecorations(element)) {
324
+ if (
325
+ isColumnControlsDecorations(element) ||
326
+ isDragColumnFloatingInsertDot(element)
327
+ ) {
316
328
  const { state, dispatch } = view;
317
329
  const { insertColumnButtonIndex } = getPluginState(state);
318
330
  const [startIndex, endIndex] = getColumnOrRowIndex(element);
@@ -330,7 +342,7 @@ export const handleMouseMove = (
330
342
  }
331
343
  }
332
344
 
333
- if (isRowControlsButton(element)) {
345
+ if (isRowControlsButton(element) || isDragRowFloatingInsertDot(element)) {
334
346
  const { state, dispatch } = view;
335
347
  const { insertRowButtonIndex } = getPluginState(state);
336
348
  const [startIndex, endIndex] = getColumnOrRowIndex(element);
@@ -383,8 +383,8 @@ const tablesPlugin: TablePlugin = ({ config: options, api }) => {
383
383
  insertRowButtonIndex,
384
384
  isHeaderColumnEnabled,
385
385
  isHeaderRowEnabled,
386
- tableWrapperTarget,
387
386
  isDragAndDropEnabled,
387
+ tableWrapperTarget,
388
388
  } = tablePluginState!;
389
389
 
390
390
  const { allowControls } = pluginConfig;
@@ -444,6 +444,7 @@ const tablesPlugin: TablePlugin = ({ config: options, api }) => {
444
444
  insertRowButtonIndex={insertRowButtonIndex}
445
445
  isHeaderColumnEnabled={isHeaderColumnEnabled}
446
446
  isHeaderRowEnabled={isHeaderRowEnabled}
447
+ isDragAndDropEnabled={isDragAndDropEnabled}
447
448
  editorView={editorView}
448
449
  mountPoint={popupsMountPoint}
449
450
  boundariesElement={popupsBoundariesElement}
@@ -483,7 +484,7 @@ const tablesPlugin: TablePlugin = ({ config: options, api }) => {
483
484
  isOpen={!!dragAndDropState?.isDragMenuOpen && !isResizing}
484
485
  />
485
486
  )}
486
- {allowControls && !isResizing && (
487
+ {allowControls && !isDragAndDropEnabled && !isResizing && (
487
488
  <FloatingDeleteButton
488
489
  editorView={editorView}
489
490
  selection={editorView.state.selection}
@@ -40,8 +40,7 @@ export const handleDocOrSelectionChanged = (
40
40
  } else if (
41
41
  tr.docChanged ||
42
42
  tr.selection instanceof CellSelection ||
43
- changedResizing ||
44
- tr.getMeta(tablePluginKey)?.type === 'HOVER_CELL'
43
+ changedResizing
45
44
  ) {
46
45
  return buildColumnControlsDecorations({
47
46
  decorationSet,
@@ -72,11 +71,6 @@ export const createPlugin = () => {
72
71
  apply: (tr, decorationSet, oldState, newState) => {
73
72
  let pluginState = decorationSet;
74
73
  const meta = tr.getMeta(tablePluginKey);
75
- const previousHover = tablePluginKey.getState(oldState)?.hoveredCell;
76
- const newHover = tablePluginKey.getState(newState)?.hoveredCell;
77
- const changedCellHover =
78
- previousHover?.colIndex !== newHover?.colIndex ||
79
- previousHover?.rowIndex !== newHover?.rowIndex;
80
74
 
81
75
  if (meta && meta.data && meta.data.decorationSet) {
82
76
  pluginState = meta.data.decorationSet;
@@ -85,8 +79,7 @@ export const createPlugin = () => {
85
79
  if (
86
80
  tr.docChanged ||
87
81
  tr.selectionSet ||
88
- tr.getMeta(tableWidthPluginKey) ||
89
- changedCellHover
82
+ tr.getMeta(tableWidthPluginKey)
90
83
  ) {
91
84
  pluginState = pluginState.map(tr.mapping, tr.doc);
92
85
  return handleDocOrSelectionChanged(
@@ -15,7 +15,6 @@ import {
15
15
  findControlsHoverDecoration,
16
16
  updateDecorations,
17
17
  } from '../../../utils/decoration';
18
- import { pluginKey as tablePluginKey } from '../../plugin-key';
19
18
 
20
19
  import { composeDecorations } from './compose-decorations';
21
20
  import type { DecorationTransformer } from './types';
@@ -50,10 +49,9 @@ const maybeUpdateColumnControlsDecoration: DecorationTransformer = ({
50
49
  tr,
51
50
  }): DecorationSet => {
52
51
  const table = findTable(tr.selection);
53
- const meta = tr.getMeta(tablePluginKey);
54
52
 
55
53
  // avoid re-drawing state if dnd decorations don't need to be updated
56
- if (!table && meta?.type !== 'HOVER_CELL') {
54
+ if (!table) {
57
55
  return decorationSet;
58
56
  }
59
57
 
@@ -6,6 +6,7 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
6
6
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
7
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import { getCellsInRow } from '@atlaskit/editor-tables/utils';
9
+ import { autoScroller } from '@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-autoscroll';
9
10
  import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
10
11
 
11
12
  import type { DraggableSourceData } from '../../types';
@@ -96,7 +97,14 @@ export const createPlugin = (
96
97
  // watch for changes
97
98
  return localId === tableNode?.attrs.localId;
98
99
  },
100
+ onDragStart: ({ location }) => {
101
+ autoScroller.start({ input: location.current.input });
102
+ },
99
103
  onDrag(event) {
104
+ autoScroller.updateInput({
105
+ input: event.location.current.input,
106
+ });
107
+
100
108
  const data = getDraggableDataFromEvent(event);
101
109
  // If no data can be found then it's most like we do not want to perform any drag actions
102
110
  if (!data) {
@@ -118,6 +126,7 @@ export const createPlugin = (
118
126
  );
119
127
  },
120
128
  onDrop(event) {
129
+ autoScroller.stop();
121
130
  const data = getDraggableDataFromEvent(event);
122
131
 
123
132
  // If no data can be found then it's most like we do not want to perform any drop action
@@ -293,6 +293,10 @@ export const TableCssClassName = {
293
293
  CONTROLS_BUTTON_OVERLAY: `${tablePrefixSelector}-controls__button-overlay`,
294
294
  LAYOUT_BUTTON: `${tablePrefixSelector}-layout-button`,
295
295
 
296
+ DRAG_CONTROLS_INSERT_BUTTON: `${tablePrefixSelector}-controls__drag-insert-button`,
297
+ DRAG_CONTROLS_INSERT_BUTTON_INNER: `${tablePrefixSelector}-controls__drag-insert-button-inner`,
298
+ DRAG_CONTROLS_INSERT_BUTTON_WRAP: `${tablePrefixSelector}-controls__drag-insert-button-wrap`,
299
+
296
300
  CONTROLS_INSERT_MARKER: `${tablePrefixSelector}-controls__insert-marker`,
297
301
  CONTROLS_INSERT_COLUMN: `${tablePrefixSelector}-controls__insert-column`,
298
302
  CONTROLS_INSERT_ROW: `${tablePrefixSelector}-controls__insert-row`,
@@ -308,8 +312,14 @@ export const TableCssClassName = {
308
312
  CONTROLS_CORNER_BUTTON: `${tablePrefixSelector}-corner-button`,
309
313
 
310
314
  /** Controls with drag handle */
311
- COLUMN_CONTROLS_WITH_DRAG: `${tablePrefixSelector}-column-controls-with-drag`,
312
- ROW_CONTROLS_WITH_DRAG: `${tablePrefixSelector}-row-controls-with-drag`,
315
+ DRAG_ROW_CONTROLS: `${tablePrefixSelector}-drag-row-controls`,
316
+ DRAG_ROW_FLOATING_INSERT_DOT_WRAPPER: `${tablePrefixSelector}-drag-row-floating-insert-dot-wrapper`,
317
+ DRAG_ROW_FLOATING_INSERT_DOT: `${tablePrefixSelector}-drag-row-floating-insert-dot`,
318
+
319
+ DRAG_COLUMN_CONTROLS: `${tablePrefixSelector}-drag-column-controls`,
320
+ DRAG_COLUMN_FLOATING_INSERT_DOT_WRAPPER: `${tablePrefixSelector}-drag-columns-floating-insert-dot-wrapper`,
321
+ DRAG_COLUMN_FLOATING_INSERT_DOT: `${tablePrefixSelector}-drag-columns-floating-insert-dot`,
322
+
313
323
  DRAG_HANDLE_BUTTON_CONTAINER: `${tablePrefixSelector}-drag-handle-button-container`,
314
324
 
315
325
  /** Other classes */
@@ -5,6 +5,7 @@ import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
5
5
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
6
6
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
7
  import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
8
+ import { TableMap } from '@atlaskit/editor-tables/table-map';
8
9
 
9
10
  import type { TableDirection } from '../../types';
10
11
  import { dragMenuDropdownWidth } from '../consts';
@@ -49,11 +50,17 @@ const FloatingDragMenu = ({
49
50
  if (!targetCellRef) {
50
51
  return null;
51
52
  }
52
-
53
+ const tableMap = tableNode ? TableMap.get(tableNode) : undefined;
54
+ const offset =
55
+ direction === 'row'
56
+ ? [7, 0]
57
+ : index === (tableMap?.width || 1) - 1
58
+ ? [14, 0]
59
+ : [-14, 0];
53
60
  // TODO: we will need to adjust the alignment and offset values depending on whether this is a row or column menu.
54
61
  return (
55
62
  <Popup
56
- alignX="left"
63
+ alignX={direction === 'row' ? 'left' : 'center'}
57
64
  alignY="top"
58
65
  target={targetCellRef as HTMLElement}
59
66
  mountTo={mountPoint}
@@ -64,7 +71,7 @@ const FloatingDragMenu = ({
64
71
  // in table, but below floating dialogs like typeaheads, pickers, etc.
65
72
  zIndex={akEditorFloatingOverlapPanelZIndex}
66
73
  forcePlacement={true}
67
- offset={[7, 0]}
74
+ offset={offset}
68
75
  stick={true}
69
76
  >
70
77
  <DragMenu
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
1
2
  import type { SyntheticEvent } from 'react';
2
3
  import React from 'react';
3
4
 
@@ -20,7 +21,7 @@ import { tableToolbarSize } from '../consts';
20
21
  import tableMessages from '../messages';
21
22
 
22
23
  export interface ButtonProps {
23
- direction: TableDirection;
24
+ type: TableDirection;
24
25
  tableRef: HTMLElement;
25
26
  onMouseDown: (event: SyntheticEvent<HTMLButtonElement>) => void;
26
27
  hasStickyHeaders: boolean;
@@ -52,7 +53,10 @@ const getToolbarSize = (tableRef: HTMLElement): number => {
52
53
  return tableToolbarSize;
53
54
  };
54
55
 
55
- const getInsertLineWidth = (tableRef: HTMLElement) => {
56
+ const getInsertLineWidth = (
57
+ tableRef: HTMLElement,
58
+ isDragAndDropEnabled?: boolean,
59
+ ) => {
56
60
  // The line gets width 100% from the table,
57
61
  // but since we have an overflow on the left,
58
62
  // we should add an offset to make up for it.
@@ -61,7 +65,7 @@ const getInsertLineWidth = (tableRef: HTMLElement) => {
61
65
  const parentOffsetWidth = parentElement!.offsetWidth;
62
66
  const { scrollLeft } = parentElement!;
63
67
  const diff = offsetWidth - parentOffsetWidth;
64
- const toolbarSize = getToolbarSize(tableRef);
68
+ const toolbarSize = isDragAndDropEnabled ? 0 : getToolbarSize(tableRef);
65
69
  return (
66
70
  Math.min(
67
71
  offsetWidth + toolbarSize,
@@ -74,10 +78,80 @@ const tooltipMessageByType = (type: TableDirection) => {
74
78
  return type === 'row' ? tableMessages.insertRow : tableMessages.insertColumn;
75
79
  };
76
80
 
81
+ export const InsertButtonForDragAndDrop = ({
82
+ onMouseDown,
83
+ tableRef,
84
+ type,
85
+ intl: { formatMessage },
86
+ hasStickyHeaders,
87
+ }: ButtonProps & WrappedComponentProps) => {
88
+ const content = (
89
+ <Tooltip
90
+ content={
91
+ <ToolTipContent
92
+ description={formatMessage(tooltipMessageByType(type))}
93
+ keymap={type === 'row' ? addRowAfter : addColumnAfter}
94
+ />
95
+ }
96
+ position="top"
97
+ >
98
+ <>
99
+ <div className={ClassName.DRAG_CONTROLS_INSERT_BUTTON_INNER}>
100
+ <button
101
+ type="button"
102
+ className={ClassName.DRAG_CONTROLS_INSERT_BUTTON}
103
+ onMouseDown={onMouseDown}
104
+ >
105
+ <svg
106
+ width="10"
107
+ height="10"
108
+ viewBox="0 0 10 10"
109
+ fill="none"
110
+ xmlns="http://www.w3.org/2000/svg"
111
+ >
112
+ <path
113
+ fillRule="evenodd"
114
+ clipRule="evenodd"
115
+ d="M5.41667 4.58333V2.91667C5.41667 2.80616 5.37277 2.70018 5.29463 2.62204C5.21649 2.5439 5.11051 2.5 5 2.5C4.88949 2.5 4.78351 2.5439 4.70537 2.62204C4.62723 2.70018 4.58333 2.80616 4.58333 2.91667V4.58333H2.91667C2.80616 4.58333 2.70018 4.62723 2.62204 4.70537C2.5439 4.78351 2.5 4.88949 2.5 5C2.5 5.11051 2.5439 5.21649 2.62204 5.29463C2.70018 5.37277 2.80616 5.41667 2.91667 5.41667H4.58333V7.08333C4.58333 7.19384 4.62723 7.29982 4.70537 7.37796C4.78351 7.4561 4.88949 7.5 5 7.5C5.11051 7.5 5.21649 7.4561 5.29463 7.37796C5.37277 7.29982 5.41667 7.19384 5.41667 7.08333V5.41667H7.08333C7.19384 5.41667 7.29982 5.37277 7.37796 5.29463C7.4561 5.21649 7.5 5.11051 7.5 5C7.5 4.88949 7.4561 4.78351 7.37796 4.70537C7.29982 4.62723 7.19384 4.58333 7.08333 4.58333H5.41667Z"
116
+ fill="currentColor"
117
+ />
118
+ </svg>
119
+ </button>
120
+ </div>
121
+ <div
122
+ className={ClassName.CONTROLS_INSERT_LINE}
123
+ style={
124
+ type === 'row'
125
+ ? { width: getInsertLineWidth(tableRef, true), left: '14px' }
126
+ : { height: getInsertLineHeight(tableRef, hasStickyHeaders) - 11 }
127
+ }
128
+ />
129
+ </>
130
+ </Tooltip>
131
+ );
132
+
133
+ const floatingButtonClassName =
134
+ type === 'column'
135
+ ? ClassName.CONTROLS_FLOATING_BUTTON_COLUMN
136
+ : ClassName.CONTROLS_FLOATING_BUTTON_ROW;
137
+
138
+ return (
139
+ <div className={floatingButtonClassName}>
140
+ <div
141
+ className={`${ClassName.CONTROLS_INSERT_BUTTON_WRAP} ${ClassName.CONTROLS_INSERT_ROW}`}
142
+ >
143
+ {content}
144
+ </div>
145
+ </div>
146
+ );
147
+ };
148
+
149
+ export const DragAndDropInsertButton = injectIntl(InsertButtonForDragAndDrop);
150
+
77
151
  const InsertButton = ({
78
152
  onMouseDown,
79
153
  tableRef,
80
- direction,
154
+ type,
81
155
  intl: { formatMessage },
82
156
  hasStickyHeaders,
83
157
  }: ButtonProps & WrappedComponentProps) => {
@@ -85,8 +159,8 @@ const InsertButton = ({
85
159
  <Tooltip
86
160
  content={
87
161
  <ToolTipContent
88
- description={formatMessage(tooltipMessageByType(direction))}
89
- keymap={direction === 'row' ? addRowAfter : addColumnAfter}
162
+ description={formatMessage(tooltipMessageByType(type))}
163
+ keymap={type === 'row' ? addRowAfter : addColumnAfter}
90
164
  />
91
165
  }
92
166
  position="top"
@@ -110,7 +184,7 @@ const InsertButton = ({
110
184
  <div
111
185
  className={ClassName.CONTROLS_INSERT_LINE}
112
186
  style={
113
- direction === 'row'
187
+ type === 'row'
114
188
  ? { width: getInsertLineWidth(tableRef) }
115
189
  : { height: getInsertLineHeight(tableRef, hasStickyHeaders) }
116
190
  }
@@ -120,7 +194,7 @@ const InsertButton = ({
120
194
  );
121
195
 
122
196
  const floatingButtonClassName =
123
- direction === 'column'
197
+ type === 'column'
124
198
  ? ClassName.CONTROLS_FLOATING_BUTTON_COLUMN
125
199
  : ClassName.CONTROLS_FLOATING_BUTTON_ROW;
126
200
 
@@ -11,17 +11,26 @@ import {
11
11
  const HORIZONTAL_ALIGN_COLUMN_BUTTON = -(tableInsertColumnButtonSize / 2);
12
12
  const HORIZONTAL_ALIGN_NUMBERED_COLUMN_BUTTON =
13
13
  HORIZONTAL_ALIGN_COLUMN_BUTTON + akEditorTableNumberColumnWidth;
14
+
14
15
  const VERTICAL_ALIGN_COLUMN_BUTTON =
15
16
  tableToolbarSize + tableInsertColumnButtonOffset;
16
17
 
18
+ const VERTICAL_ALIGN_COLUMN_BUTTON_DRAG = tableInsertColumnButtonOffset;
19
+
17
20
  const HORIZONTAL_ALIGN_ROW_BUTTON = -(
18
21
  tableToolbarSize +
19
22
  tableInsertColumnButtonOffset +
20
23
  tableInsertColumnButtonSize
21
24
  );
25
+
26
+ const HORIZONTAL_ALIGN_ROW_BUTTON_DRAG = -18;
27
+
22
28
  const VERTICAL_ALIGN_ROW_BUTTON = tableInsertColumnButtonSize / 2;
23
29
 
24
- function getRowOptions(index: number): Partial<PopupProps> {
30
+ function getRowOptions(
31
+ index: number,
32
+ isDragAndDropEnabled: boolean,
33
+ ): Partial<PopupProps> {
25
34
  let defaultOptions = {
26
35
  alignX: 'left',
27
36
  alignY: 'bottom',
@@ -43,7 +52,9 @@ function getRowOptions(index: number): Partial<PopupProps> {
43
52
  return {
44
53
  ...position,
45
54
  // Left position should be always the offset (To place in the correct position even if the table has overflow).
46
- left: HORIZONTAL_ALIGN_ROW_BUTTON,
55
+ left: isDragAndDropEnabled
56
+ ? HORIZONTAL_ALIGN_ROW_BUTTON_DRAG
57
+ : HORIZONTAL_ALIGN_ROW_BUTTON,
47
58
  };
48
59
  },
49
60
  };
@@ -53,11 +64,17 @@ function getColumnOptions(
53
64
  index: number,
54
65
  tableContainer: HTMLElement | null,
55
66
  hasNumberedColumns: boolean,
67
+ isDragAndDropEnabled: boolean,
56
68
  ): Partial<PopupProps> {
57
69
  const options: Partial<PopupProps> = {
58
70
  alignX: 'end',
59
71
  alignY: 'top',
60
- offset: [HORIZONTAL_ALIGN_COLUMN_BUTTON, VERTICAL_ALIGN_COLUMN_BUTTON],
72
+ offset: [
73
+ HORIZONTAL_ALIGN_COLUMN_BUTTON,
74
+ isDragAndDropEnabled
75
+ ? VERTICAL_ALIGN_COLUMN_BUTTON_DRAG
76
+ : VERTICAL_ALIGN_COLUMN_BUTTON,
77
+ ],
61
78
  // :: (position: PopupPosition) -> PopupPosition
62
79
  // Limit the InsertButton position to the table container
63
80
  // if the left position starts before it
@@ -108,13 +125,19 @@ function getPopupOptions(
108
125
  direction: TableDirection,
109
126
  index: number,
110
127
  hasNumberedColumns: boolean,
128
+ isDragAndDropEnabled: boolean,
111
129
  tableContainer: HTMLElement | null,
112
130
  ): Partial<PopupProps> {
113
131
  switch (direction) {
114
132
  case 'column':
115
- return getColumnOptions(index, tableContainer, hasNumberedColumns);
133
+ return getColumnOptions(
134
+ index,
135
+ tableContainer,
136
+ hasNumberedColumns,
137
+ isDragAndDropEnabled,
138
+ );
116
139
  case 'row':
117
- return getRowOptions(index);
140
+ return getRowOptions(index, isDragAndDropEnabled);
118
141
  default:
119
142
  return {};
120
143
  }
@@ -34,7 +34,7 @@ import { TableCssClassName as ClassName } from '../../types';
34
34
  import { checkIfNumberColumnEnabled } from '../../utils';
35
35
 
36
36
  import getPopupOptions from './getPopupOptions';
37
- import InsertButton from './InsertButton';
37
+ import InsertButton, { DragAndDropInsertButton } from './InsertButton';
38
38
 
39
39
  export interface Props {
40
40
  editorView: EditorView;
@@ -45,6 +45,7 @@ export interface Props {
45
45
  insertRowButtonIndex?: number;
46
46
  isHeaderColumnEnabled?: boolean;
47
47
  isHeaderRowEnabled?: boolean;
48
+ isDragAndDropEnabled?: boolean;
48
49
  mountPoint?: HTMLElement;
49
50
  boundariesElement?: HTMLElement;
50
51
  scrollableElement?: HTMLElement;
@@ -76,6 +77,7 @@ export class FloatingInsertButton extends React.Component<
76
77
  boundariesElement,
77
78
  isHeaderColumnEnabled,
78
79
  isHeaderRowEnabled,
80
+ isDragAndDropEnabled,
79
81
  dispatchAnalyticsEvent,
80
82
  } = this.props;
81
83
 
@@ -199,16 +201,26 @@ export class FloatingInsertButton extends React.Component<
199
201
  type,
200
202
  index,
201
203
  hasNumberedColumns,
204
+ !!isDragAndDropEnabled,
202
205
  tableContainerWrapper,
203
206
  )}
204
207
  zIndex={zIndex}
205
208
  >
206
- <InsertButton
207
- direction={type}
208
- tableRef={tableRef}
209
- onMouseDown={type === 'column' ? this.insertColumn : this.insertRow}
210
- hasStickyHeaders={this.props.hasStickyHeaders || false}
211
- />
209
+ {isDragAndDropEnabled ? (
210
+ <DragAndDropInsertButton
211
+ type={type}
212
+ tableRef={tableRef}
213
+ onMouseDown={type === 'column' ? this.insertColumn : this.insertRow}
214
+ hasStickyHeaders={this.props.hasStickyHeaders || false}
215
+ />
216
+ ) : (
217
+ <InsertButton
218
+ type={type}
219
+ tableRef={tableRef}
220
+ onMouseDown={type === 'column' ? this.insertColumn : this.insertRow}
221
+ hasStickyHeaders={this.props.hasStickyHeaders || false}
222
+ />
223
+ )}
212
224
  </Popup>
213
225
  );
214
226
  }
@@ -5,15 +5,17 @@ import type { Selection } from '@atlaskit/editor-prosemirror/state';
5
5
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
6
6
  import { CellSelection } from '@atlaskit/editor-tables';
7
7
  import { getSelectionRect } from '@atlaskit/editor-tables/utils';
8
+ import { token } from '@atlaskit/tokens';
8
9
 
9
10
  import {
10
11
  clearHoverSelection,
11
12
  hoverColumns,
12
13
  selectColumn,
13
14
  } from '../../../commands';
15
+ import { toggleDragMenu } from '../../../pm-plugins/drag-and-drop/commands';
14
16
  import type { CellHoverMeta } from '../../../types';
15
17
  import { TableCssClassName as ClassName } from '../../../types';
16
- import { getSelectedColumnIndexes } from '../../../utils';
18
+ import { getRowsParams, getSelectedColumnIndexes } from '../../../utils';
17
19
  import { DragHandle } from '../../DragHandle';
18
20
 
19
21
  export interface ColumnControlsProps {
@@ -27,6 +29,7 @@ export interface ColumnControlsProps {
27
29
  localId?: string;
28
30
  rowHeights?: number[];
29
31
  colWidths?: (number | undefined)[];
32
+ hasHeaderColumn?: boolean;
30
33
  }
31
34
 
32
35
  const getSelectedColumns = (selection: Selection) => {
@@ -51,10 +54,13 @@ export const ColumnControls = ({
51
54
  isInDanger,
52
55
  rowHeights,
53
56
  colWidths,
57
+ hasHeaderColumn,
54
58
  }: ColumnControlsProps) => {
55
59
  const widths =
56
60
  colWidths?.map((width) => (width ? `${width - 1}px` : '0px')).join(' ') ??
57
61
  '0px';
62
+ // TODO: reusing getRowsParams here because it's generic enough to work for columns -> rename
63
+ const columnParams = getRowsParams(colWidths ?? []);
58
64
  const colIndex = hoveredCell?.colIndex;
59
65
  const selectedColIndexes = getSelectedColumns(editorView.state.selection);
60
66
 
@@ -94,8 +100,13 @@ export const ColumnControls = ({
94
100
  }
95
101
  }, [editorView, tableActive]);
96
102
 
103
+ const handleMouseUp = useCallback(() => {
104
+ const { state, dispatch } = editorView;
105
+ toggleDragMenu(undefined, 'column', colIndex)(state, dispatch);
106
+ }, [editorView, colIndex]);
107
+
97
108
  return (
98
- <div className={ClassName.COLUMN_CONTROLS_WITH_DRAG}>
109
+ <div className={ClassName.DRAG_COLUMN_CONTROLS}>
99
110
  <div
100
111
  className={ClassName.COLUMN_CONTROLS_INNER}
101
112
  data-testid="table-floating-column-controls"
@@ -104,6 +115,33 @@ export const ColumnControls = ({
104
115
  marginTop,
105
116
  }}
106
117
  >
118
+ {!isResizing &&
119
+ columnParams.map(({ startIndex, endIndex }, index) => (
120
+ <div
121
+ style={{
122
+ gridColumn: `${index + 1} / span 1`,
123
+ }}
124
+ data-start-index={startIndex}
125
+ data-end-index={endIndex}
126
+ className={ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT_WRAPPER}
127
+ contentEditable={false}
128
+ key={index}
129
+ >
130
+ {!hasHeaderColumn && index === 0 && (
131
+ <div
132
+ style={{
133
+ left: '0px',
134
+ right: 'unset',
135
+ }}
136
+ className={ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT}
137
+ />
138
+ )}
139
+ <div
140
+ className={ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT}
141
+ style={columnParams.length - 1 === index ? { right: '0' } : {}}
142
+ />
143
+ </div>
144
+ ))}
107
145
  {tableActive &&
108
146
  !isResizing &&
109
147
  !!hoveredCell &&
@@ -111,7 +149,12 @@ export const ColumnControls = ({
111
149
  <div
112
150
  style={{
113
151
  gridColumn: gridColumnPosition,
114
- marginTop: `-15px`,
152
+ zIndex: 99,
153
+ display: 'flex',
154
+ width: '100%',
155
+ justifyContent: 'center',
156
+ alignItems: 'center',
157
+ marginTop: token('space.negative.025', '-2px'),
115
158
  }}
116
159
  data-column-control-index={hoveredCell.colIndex}
117
160
  data-testid="table-floating-column-control"
@@ -132,6 +175,7 @@ export const ColumnControls = ({
132
175
  onClick={handleClick}
133
176
  onMouseOver={handleMouseOver}
134
177
  onMouseOut={handleMouseOut}
178
+ onMouseUp={handleMouseUp}
135
179
  />
136
180
  </div>
137
181
  )}
@@ -12,7 +12,11 @@ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/el
12
12
  import type { RowStickyState } from '../../pm-plugins/sticky-headers';
13
13
  import type { CellHoverMeta, DraggableSourceData } from '../../types';
14
14
  import { TableCssClassName as ClassName } from '../../types';
15
- import { getColumnsWidths, getRowHeights } from '../../utils';
15
+ import {
16
+ containsHeaderColumn,
17
+ getColumnsWidths,
18
+ getRowHeights,
19
+ } from '../../utils';
16
20
 
17
21
  import { ColumnControls } from './ColumnControls';
18
22
  import { ColumnDropTargets } from './ColumnDropTargets';
@@ -53,6 +57,7 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
53
57
  const [hasDropTargets, setHasDropTargets] = useState(false);
54
58
  const node = getNode();
55
59
  const currentNodeLocalId = node?.attrs.localId;
60
+ const hasHeaderColumn = containsHeaderColumn(node);
56
61
 
57
62
  useEffect(() => {
58
63
  if (tableRef && window?.ResizeObserver) {
@@ -118,12 +123,13 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
118
123
 
119
124
  const mountTo = (tableRef && tableRef?.parentElement) || document.body;
120
125
 
126
+ if (!tableActive) {
127
+ return null;
128
+ }
129
+
121
130
  return ReactDOM.createPortal(
122
131
  <div
123
132
  className={ClassName.COLUMN_CONTROLS_WRAPPER}
124
- style={{
125
- pointerEvents: 'none',
126
- }}
127
133
  data-testid="table-floating-column-controls-wrapper"
128
134
  >
129
135
  <ColumnControls
@@ -137,6 +143,7 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
137
143
  isInDanger={isInDanger}
138
144
  rowHeights={rowHeights}
139
145
  colWidths={colWidths}
146
+ hasHeaderColumn={hasHeaderColumn}
140
147
  />
141
148
  {hasDropTargets && (
142
149
  <ColumnDropTargets