@atlaskit/editor-plugin-table 5.3.12 → 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 (155) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/plugins/table/event-handlers.js +6 -3
  3. package/dist/cjs/plugins/table/index.js +16 -2
  4. package/dist/cjs/plugins/table/nodeviews/TableComponent.js +2 -1
  5. package/dist/cjs/plugins/table/pm-plugins/decorations/plugin.js +3 -7
  6. package/dist/cjs/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  7. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/actions.js +2 -1
  8. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/commands.js +22 -1
  9. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/plugin.js +54 -7
  10. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/reducer.js +6 -0
  11. package/dist/cjs/plugins/table/types.js +9 -2
  12. package/dist/cjs/plugins/table/ui/DragHandle/index.js +2 -0
  13. package/dist/cjs/plugins/table/ui/FloatingDragMenu/DragMenu.js +80 -0
  14. package/dist/cjs/plugins/table/ui/FloatingDragMenu/index.js +62 -0
  15. package/dist/cjs/plugins/table/ui/FloatingInsertButton/InsertButton.js +52 -4
  16. package/dist/cjs/plugins/table/ui/FloatingInsertButton/getPopupOptions.js +10 -8
  17. package/dist/cjs/plugins/table/ui/FloatingInsertButton/index.js +12 -3
  18. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +44 -5
  19. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/index.js +6 -4
  20. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +44 -20
  21. package/dist/cjs/plugins/table/ui/TableFloatingControls/index.js +4 -0
  22. package/dist/cjs/plugins/table/ui/common-styles.js +1 -1
  23. package/dist/cjs/plugins/table/ui/consts.js +3 -2
  24. package/dist/cjs/plugins/table/ui/ui-styles.js +27 -24
  25. package/dist/cjs/plugins/table/utils/dom.js +12 -4
  26. package/dist/cjs/plugins/table/utils/drag-menu.js +59 -0
  27. package/dist/cjs/plugins/table/utils/index.js +12 -0
  28. package/dist/es2019/plugins/table/event-handlers.js +5 -4
  29. package/dist/es2019/plugins/table/index.js +16 -2
  30. package/dist/es2019/plugins/table/nodeviews/TableComponent.js +2 -1
  31. package/dist/es2019/plugins/table/pm-plugins/decorations/plugin.js +3 -7
  32. package/dist/es2019/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  33. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/actions.js +2 -1
  34. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/commands.js +20 -0
  35. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/plugin.js +54 -3
  36. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/reducer.js +7 -0
  37. package/dist/es2019/plugins/table/types.js +9 -2
  38. package/dist/es2019/plugins/table/ui/DragHandle/index.js +2 -0
  39. package/dist/es2019/plugins/table/ui/FloatingDragMenu/DragMenu.js +77 -0
  40. package/dist/es2019/plugins/table/ui/FloatingDragMenu/index.js +56 -0
  41. package/dist/es2019/plugins/table/ui/FloatingInsertButton/InsertButton.js +53 -2
  42. package/dist/es2019/plugins/table/ui/FloatingInsertButton/getPopupOptions.js +10 -8
  43. package/dist/es2019/plugins/table/ui/FloatingInsertButton/index.js +9 -3
  44. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +46 -6
  45. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/index.js +7 -5
  46. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +45 -22
  47. package/dist/es2019/plugins/table/ui/TableFloatingControls/index.js +4 -0
  48. package/dist/es2019/plugins/table/ui/common-styles.js +51 -3
  49. package/dist/es2019/plugins/table/ui/consts.js +2 -1
  50. package/dist/es2019/plugins/table/ui/ui-styles.js +23 -1
  51. package/dist/es2019/plugins/table/utils/dom.js +5 -1
  52. package/dist/es2019/plugins/table/utils/drag-menu.js +44 -0
  53. package/dist/es2019/plugins/table/utils/index.js +1 -1
  54. package/dist/esm/plugins/table/event-handlers.js +7 -4
  55. package/dist/esm/plugins/table/index.js +16 -2
  56. package/dist/esm/plugins/table/nodeviews/TableComponent.js +2 -1
  57. package/dist/esm/plugins/table/pm-plugins/decorations/plugin.js +3 -7
  58. package/dist/esm/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  59. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/actions.js +2 -1
  60. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/commands.js +21 -0
  61. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/plugin.js +54 -7
  62. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/reducer.js +6 -0
  63. package/dist/esm/plugins/table/types.js +9 -2
  64. package/dist/esm/plugins/table/ui/DragHandle/index.js +2 -0
  65. package/dist/esm/plugins/table/ui/FloatingDragMenu/DragMenu.js +73 -0
  66. package/dist/esm/plugins/table/ui/FloatingDragMenu/index.js +55 -0
  67. package/dist/esm/plugins/table/ui/FloatingInsertButton/InsertButton.js +51 -3
  68. package/dist/esm/plugins/table/ui/FloatingInsertButton/getPopupOptions.js +10 -8
  69. package/dist/esm/plugins/table/ui/FloatingInsertButton/index.js +9 -3
  70. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +45 -6
  71. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/index.js +7 -5
  72. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +46 -22
  73. package/dist/esm/plugins/table/ui/TableFloatingControls/index.js +4 -0
  74. package/dist/esm/plugins/table/ui/common-styles.js +2 -2
  75. package/dist/esm/plugins/table/ui/consts.js +2 -1
  76. package/dist/esm/plugins/table/ui/ui-styles.js +26 -23
  77. package/dist/esm/plugins/table/utils/dom.js +11 -3
  78. package/dist/esm/plugins/table/utils/drag-menu.js +52 -0
  79. package/dist/esm/plugins/table/utils/index.js +1 -1
  80. package/dist/types/plugins/table/pm-plugins/drag-and-drop/actions.d.ts +8 -1
  81. package/dist/types/plugins/table/pm-plugins/drag-and-drop/commands.d.ts +2 -1
  82. package/dist/types/plugins/table/pm-plugins/drag-and-drop/types.d.ts +4 -0
  83. package/dist/types/plugins/table/types.d.ts +10 -2
  84. package/dist/types/plugins/table/ui/DragHandle/index.d.ts +4 -2
  85. package/dist/types/plugins/table/ui/DragPreview/index.d.ts +2 -1
  86. package/dist/types/plugins/table/ui/FloatingDeleteButton/index.d.ts +2 -1
  87. package/dist/types/plugins/table/ui/FloatingDeleteButton/types.d.ts +2 -1
  88. package/dist/types/plugins/table/ui/FloatingDragMenu/DragMenu.d.ts +19 -0
  89. package/dist/types/plugins/table/ui/FloatingDragMenu/index.d.ts +21 -0
  90. package/dist/types/plugins/table/ui/FloatingInsertButton/InsertButton.d.ts +6 -1
  91. package/dist/types/plugins/table/ui/FloatingInsertButton/getPopupOptions.d.ts +2 -1
  92. package/dist/types/plugins/table/ui/FloatingInsertButton/index.d.ts +5 -5
  93. package/dist/types/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -1
  94. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +4 -0
  95. package/dist/types/plugins/table/ui/TableFloatingControls/index.d.ts +3 -0
  96. package/dist/types/plugins/table/ui/consts.d.ts +1 -0
  97. package/dist/types/plugins/table/ui/ui-styles.d.ts +1 -0
  98. package/dist/types/plugins/table/utils/dom.d.ts +4 -1
  99. package/dist/types/plugins/table/utils/drag-menu.d.ts +7 -0
  100. package/dist/types/plugins/table/utils/index.d.ts +1 -1
  101. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/actions.d.ts +8 -1
  102. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/commands.d.ts +2 -1
  103. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/types.d.ts +4 -0
  104. package/dist/types-ts4.5/plugins/table/types.d.ts +10 -2
  105. package/dist/types-ts4.5/plugins/table/ui/DragHandle/index.d.ts +4 -2
  106. package/dist/types-ts4.5/plugins/table/ui/DragPreview/index.d.ts +2 -1
  107. package/dist/types-ts4.5/plugins/table/ui/FloatingDeleteButton/index.d.ts +2 -1
  108. package/dist/types-ts4.5/plugins/table/ui/FloatingDeleteButton/types.d.ts +2 -1
  109. package/dist/types-ts4.5/plugins/table/ui/FloatingDragMenu/DragMenu.d.ts +19 -0
  110. package/dist/types-ts4.5/plugins/table/ui/FloatingDragMenu/index.d.ts +21 -0
  111. package/dist/types-ts4.5/plugins/table/ui/FloatingInsertButton/InsertButton.d.ts +6 -1
  112. package/dist/types-ts4.5/plugins/table/ui/FloatingInsertButton/getPopupOptions.d.ts +2 -1
  113. package/dist/types-ts4.5/plugins/table/ui/FloatingInsertButton/index.d.ts +5 -5
  114. package/dist/types-ts4.5/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -1
  115. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +4 -0
  116. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/index.d.ts +3 -0
  117. package/dist/types-ts4.5/plugins/table/ui/consts.d.ts +1 -0
  118. package/dist/types-ts4.5/plugins/table/ui/ui-styles.d.ts +1 -0
  119. package/dist/types-ts4.5/plugins/table/utils/dom.d.ts +4 -1
  120. package/dist/types-ts4.5/plugins/table/utils/drag-menu.d.ts +7 -0
  121. package/dist/types-ts4.5/plugins/table/utils/index.d.ts +1 -1
  122. package/package.json +3 -2
  123. package/src/__tests__/unit/pm-plugins/decorations/plugin.ts +40 -194
  124. package/src/__tests__/unit/ui/RowDragControls.tsx +9 -11
  125. package/src/plugins/table/event-handlers.ts +15 -3
  126. package/src/plugins/table/index.tsx +18 -1
  127. package/src/plugins/table/nodeviews/TableComponent.tsx +2 -1
  128. package/src/plugins/table/pm-plugins/decorations/plugin.ts +2 -9
  129. package/src/plugins/table/pm-plugins/decorations/utils/column-controls.ts +1 -3
  130. package/src/plugins/table/pm-plugins/drag-and-drop/actions.ts +14 -1
  131. package/src/plugins/table/pm-plugins/drag-and-drop/commands.ts +32 -1
  132. package/src/plugins/table/pm-plugins/drag-and-drop/plugin.ts +50 -2
  133. package/src/plugins/table/pm-plugins/drag-and-drop/reducer.ts +7 -0
  134. package/src/plugins/table/pm-plugins/drag-and-drop/types.ts +5 -0
  135. package/src/plugins/table/types.ts +14 -2
  136. package/src/plugins/table/ui/DragHandle/index.tsx +5 -1
  137. package/src/plugins/table/ui/DragPreview/index.tsx +2 -1
  138. package/src/plugins/table/ui/FloatingDeleteButton/index.tsx +2 -1
  139. package/src/plugins/table/ui/FloatingDeleteButton/types.ts +3 -1
  140. package/src/plugins/table/ui/FloatingDragMenu/DragMenu.tsx +99 -0
  141. package/src/plugins/table/ui/FloatingDragMenu/index.tsx +91 -0
  142. package/src/plugins/table/ui/FloatingInsertButton/InsertButton.tsx +79 -4
  143. package/src/plugins/table/ui/FloatingInsertButton/getPopupOptions.ts +31 -7
  144. package/src/plugins/table/ui/FloatingInsertButton/index.tsx +28 -13
  145. package/src/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.tsx +47 -3
  146. package/src/plugins/table/ui/TableFloatingColumnControls/index.tsx +11 -4
  147. package/src/plugins/table/ui/TableFloatingControls/RowControls/DragControls.tsx +65 -25
  148. package/src/plugins/table/ui/TableFloatingControls/index.tsx +7 -0
  149. package/src/plugins/table/ui/common-styles.ts +57 -2
  150. package/src/plugins/table/ui/consts.ts +2 -0
  151. package/src/plugins/table/ui/ui-styles.ts +27 -1
  152. package/src/plugins/table/utils/dom.ts +11 -4
  153. package/src/plugins/table/utils/drag-menu.ts +65 -0
  154. package/src/plugins/table/utils/index.ts +2 -0
  155. package/tsconfig.app.json +3 -0
@@ -1,23 +1,26 @@
1
1
  import React from 'react';
2
2
 
3
- import { injectIntl, WrappedComponentProps } from 'react-intl-next';
3
+ import type { WrappedComponentProps } from 'react-intl-next';
4
+ import { injectIntl } from 'react-intl-next';
4
5
 
5
- import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
6
+ import type {
7
+ AnalyticsEventPayload,
8
+ DispatchAnalyticsEvent,
9
+ EditorAnalyticsAPI,
10
+ } from '@atlaskit/editor-common/analytics';
6
11
  import {
7
12
  ACTION,
8
13
  ACTION_SUBJECT,
9
- AnalyticsEventPayload,
10
14
  CONTENT_COMPONENT,
11
- DispatchAnalyticsEvent,
12
15
  EVENT_TYPE,
13
16
  INPUT_METHOD,
14
17
  } from '@atlaskit/editor-common/analytics';
15
18
  import type { GetEditorContainerWidth } from '@atlaskit/editor-common/types';
16
19
  import { Popup } from '@atlaskit/editor-common/ui';
17
20
  import { closestElement } from '@atlaskit/editor-common/utils';
18
- import { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
21
+ import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
19
22
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
20
- import { EditorView } from '@atlaskit/editor-prosemirror/view';
23
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
21
24
  import { akEditorTableCellOnStickyHeaderZIndex } from '@atlaskit/editor-shared-styles';
22
25
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
23
26
  import { TableMap } from '@atlaskit/editor-tables/table-map';
@@ -31,7 +34,7 @@ import { TableCssClassName as ClassName } from '../../types';
31
34
  import { checkIfNumberColumnEnabled } from '../../utils';
32
35
 
33
36
  import getPopupOptions from './getPopupOptions';
34
- import InsertButton from './InsertButton';
37
+ import InsertButton, { DragAndDropInsertButton } from './InsertButton';
35
38
 
36
39
  export interface Props {
37
40
  editorView: EditorView;
@@ -42,6 +45,7 @@ export interface Props {
42
45
  insertRowButtonIndex?: number;
43
46
  isHeaderColumnEnabled?: boolean;
44
47
  isHeaderRowEnabled?: boolean;
48
+ isDragAndDropEnabled?: boolean;
45
49
  mountPoint?: HTMLElement;
46
50
  boundariesElement?: HTMLElement;
47
51
  scrollableElement?: HTMLElement;
@@ -73,6 +77,7 @@ export class FloatingInsertButton extends React.Component<
73
77
  boundariesElement,
74
78
  isHeaderColumnEnabled,
75
79
  isHeaderRowEnabled,
80
+ isDragAndDropEnabled,
76
81
  dispatchAnalyticsEvent,
77
82
  } = this.props;
78
83
 
@@ -196,16 +201,26 @@ export class FloatingInsertButton extends React.Component<
196
201
  type,
197
202
  index,
198
203
  hasNumberedColumns,
204
+ !!isDragAndDropEnabled,
199
205
  tableContainerWrapper,
200
206
  )}
201
207
  zIndex={zIndex}
202
208
  >
203
- <InsertButton
204
- type={type}
205
- tableRef={tableRef}
206
- onMouseDown={type === 'column' ? this.insertColumn : this.insertRow}
207
- hasStickyHeaders={this.props.hasStickyHeaders || false}
208
- />
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
+ )}
209
224
  </Popup>
210
225
  );
211
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
@@ -4,23 +4,33 @@ import React, { useCallback, useMemo } from 'react';
4
4
  import { injectIntl } from 'react-intl-next';
5
5
  import type { WrappedComponentProps } from 'react-intl-next';
6
6
 
7
+ import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
7
8
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
8
9
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
9
10
  import { CellSelection } from '@atlaskit/editor-tables';
10
- import { findTable, getSelectionRect } from '@atlaskit/editor-tables/utils';
11
+ import { getSelectionRect } from '@atlaskit/editor-tables/utils';
12
+ import { token } from '@atlaskit/tokens';
11
13
 
12
14
  import { clearHoverSelection } from '../../../commands';
15
+ import { toggleDragMenu } from '../../../pm-plugins/drag-and-drop/commands';
13
16
  import type { CellHoverMeta } from '../../../types';
14
17
  import { TableCssClassName as ClassName } from '../../../types';
15
- import { getRowHeights, getSelectedRowIndexes } from '../../../utils';
18
+ import {
19
+ getRowHeights,
20
+ getRowsParams,
21
+ getSelectedRowIndexes,
22
+ } from '../../../utils';
16
23
  import { DragHandle } from '../../DragHandle';
17
24
 
18
25
  type DragControlsProps = {
19
26
  editorView: EditorView;
20
27
  tableRef: HTMLTableElement;
28
+ tableNode?: PmNode;
21
29
  tableActive?: boolean;
22
30
  hoveredCell?: CellHoverMeta;
23
31
  isInDanger?: boolean;
32
+ isResizing?: boolean;
33
+ hasHeaderRow?: boolean;
24
34
  hoverRows: (rows: number[], danger?: boolean) => void;
25
35
  selectRow: (row: number, expand: boolean) => void;
26
36
  updateCellHoverLocation: (rowIndex: number) => void;
@@ -39,18 +49,31 @@ const getSelectedRows = (selection: Selection) => {
39
49
 
40
50
  const DragControlsComponent = ({
41
51
  tableRef,
52
+ tableNode,
42
53
  hoveredCell,
43
54
  tableActive,
44
55
  editorView,
45
56
  isInDanger,
57
+ isResizing,
58
+ hasHeaderRow,
46
59
  hoverRows,
47
60
  selectRow,
48
61
  updateCellHoverLocation,
49
62
  }: DragControlsProps & WrappedComponentProps) => {
50
63
  const rowHeights = getRowHeights(tableRef);
64
+ const rowsParams = getRowsParams(rowHeights);
51
65
  const heights = rowHeights.map((height) => `${height - 1}px`).join(' ');
52
66
  const selectedRowIndexes = getSelectedRows(editorView.state.selection);
53
67
  const rowWidth = tableRef.offsetWidth;
68
+
69
+ const onMouseUp = useCallback(() => {
70
+ toggleDragMenu(
71
+ undefined,
72
+ 'row',
73
+ hoveredCell?.rowIndex,
74
+ )(editorView.state, editorView.dispatch);
75
+ }, [editorView, hoveredCell?.rowIndex]);
76
+
54
77
  const rowIndex = hoveredCell?.rowIndex;
55
78
 
56
79
  const gridRowPosition = useMemo(() => {
@@ -61,11 +84,6 @@ const DragControlsComponent = ({
61
84
  return `${rowIndex! + 1} / span 1`;
62
85
  }, [rowIndex, selectedRowIndexes]);
63
86
 
64
- const getLocalId = () => {
65
- const tableNode = findTable(editorView.state.selection);
66
- return tableNode?.node?.attrs?.localId || '';
67
- };
68
-
69
87
  const handleMouseOut = useCallback(() => {
70
88
  if (tableActive) {
71
89
  const { state, dispatch } = editorView;
@@ -75,25 +93,21 @@ const DragControlsComponent = ({
75
93
 
76
94
  const handleMouseMove = useCallback(
77
95
  (e: MouseEvent) => {
78
- // avoid updating if event target is drag handle
79
- if (
80
- !(e.nativeEvent.target as Element).classList.contains(
81
- ClassName.ROW_CONTROLS_WITH_DRAG,
82
- )
83
- ) {
96
+ const isParentDragControls = (e.nativeEvent.target as Element).closest(
97
+ `.${ClassName.DRAG_ROW_CONTROLS}`,
98
+ );
99
+ const rowIndex = (e.nativeEvent.target as Element).getAttribute(
100
+ 'data-start-index',
101
+ );
102
+
103
+ // avoid updating if event target is not related
104
+ if (!isParentDragControls || !rowIndex) {
84
105
  return;
85
106
  }
86
107
 
87
- const hoverHeight = e.nativeEvent.offsetY;
88
- let totalHeight = 0;
89
- const rowIndex = rowHeights.findIndex((row) => {
90
- totalHeight += row;
91
- return hoverHeight <= totalHeight;
92
- });
93
-
94
- updateCellHoverLocation(rowIndex);
108
+ updateCellHoverLocation(Number(rowIndex));
95
109
  },
96
- [updateCellHoverLocation, rowHeights],
110
+ [updateCellHoverLocation],
97
111
  );
98
112
 
99
113
  const handleMouseOver = useCallback(() => {
@@ -109,13 +123,37 @@ const DragControlsComponent = ({
109
123
 
110
124
  return (
111
125
  <div
112
- className={ClassName.ROW_CONTROLS_WITH_DRAG}
126
+ className={ClassName.DRAG_ROW_CONTROLS}
113
127
  style={{
114
128
  gridTemplateRows: heights,
115
129
  }}
116
130
  onMouseMove={handleMouseMove}
117
131
  >
118
- {Number.isFinite(rowIndex) && (
132
+ {!isResizing &&
133
+ rowsParams.map(({ startIndex, endIndex }, index) => (
134
+ <div
135
+ style={{
136
+ gridRow: `${index + 1} / span 1`,
137
+ }}
138
+ data-start-index={startIndex}
139
+ data-end-index={endIndex}
140
+ className={ClassName.DRAG_ROW_FLOATING_INSERT_DOT_WRAPPER}
141
+ contentEditable={false}
142
+ key={index}
143
+ >
144
+ {!hasHeaderRow && index === 0 && (
145
+ <div
146
+ style={{
147
+ top: '0px',
148
+ left: token('space.075', '6px'),
149
+ }}
150
+ className={ClassName.DRAG_ROW_FLOATING_INSERT_DOT}
151
+ />
152
+ )}
153
+ <div className={ClassName.DRAG_ROW_FLOATING_INSERT_DOT} />
154
+ </div>
155
+ ))}
156
+ {!isResizing && Number.isFinite(rowIndex) && (
119
157
  <div
120
158
  style={{
121
159
  gridRow: gridRowPosition,
@@ -124,9 +162,10 @@ const DragControlsComponent = ({
124
162
  alignItems: 'center',
125
163
  justifyContent: 'center',
126
164
  }}
165
+ data-testid="table-floating-row-drag-handle"
127
166
  >
128
167
  <DragHandle
129
- tableLocalId={getLocalId()}
168
+ tableLocalId={tableNode?.attrs?.localId ?? ''}
130
169
  indexes={[rowIndex!]}
131
170
  previewWidth={rowWidth}
132
171
  previewHeight={rowHeights[rowIndex!]}
@@ -140,6 +179,7 @@ const DragControlsComponent = ({
140
179
  onClick={handleClick}
141
180
  onMouseOver={handleMouseOver}
142
181
  onMouseOut={handleMouseOut}
182
+ onMouseUp={onMouseUp}
143
183
  />
144
184
  </div>
145
185
  )}
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
2
2
 
3
3
  import type { TableColumnOrdering } from '@atlaskit/custom-steps';
4
4
  import { browser } from '@atlaskit/editor-common/utils';
5
+ import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
5
6
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
6
7
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
8
 
@@ -19,6 +20,7 @@ export interface Props {
19
20
  editorView: EditorView;
20
21
  selection?: Selection;
21
22
  tableRef?: HTMLTableElement;
23
+ tableNode?: PmNode;
22
24
  tableActive?: boolean;
23
25
  isInDanger?: boolean;
24
26
  isResizing?: boolean;
@@ -32,6 +34,7 @@ export interface Props {
32
34
  hoveredCell?: CellHoverMeta;
33
35
  ordering?: TableColumnOrdering;
34
36
  stickyHeader?: RowStickyState;
37
+ insertRowButtonIndex?: number;
35
38
  }
36
39
 
37
40
  interface State {
@@ -111,6 +114,7 @@ export default class TableFloatingControls extends Component<Props, State> {
111
114
  const {
112
115
  editorView,
113
116
  tableRef,
117
+ tableNode,
114
118
  isInDanger,
115
119
  isResizing,
116
120
  isNumberColumnEnabled,
@@ -157,10 +161,13 @@ export default class TableFloatingControls extends Component<Props, State> {
157
161
  {isDragAndDropEnabled ? (
158
162
  <DragControls
159
163
  tableRef={tableRef}
164
+ tableNode={tableNode}
160
165
  hoveredCell={hoveredCell}
161
166
  editorView={editorView}
162
167
  tableActive={tableActive}
163
168
  isInDanger={isInDanger}
169
+ isResizing={isResizing}
170
+ hasHeaderRow={hasHeaderRow}
164
171
  hoverRows={this.hoverRows}
165
172
  selectRow={this.selectRow}
166
173
  updateCellHoverLocation={this.updateCellHoverLocation}
@@ -56,6 +56,7 @@ import {
56
56
  columnControlsDecoration,
57
57
  columnControlsLineMarker,
58
58
  DeleteButton,
59
+ dragInsertButtonWrapper,
59
60
  floatingColumnControls,
60
61
  HeaderButton,
61
62
  HeaderButtonDanger,
@@ -357,6 +358,8 @@ export const tableStyles = (
357
358
  ${insertRowButtonWrapper(props)}
358
359
  }
359
360
 
361
+ ${dragInsertButtonWrapper(props)}
362
+
360
363
  /* Delete button */
361
364
  ${DeleteButton(props)}
362
365
  /* Ends Delete button */
@@ -700,12 +703,64 @@ export const tableStyles = (
700
703
  )}
701
704
  }
702
705
 
703
- .${ClassName.ROW_CONTROLS_WITH_DRAG} {
706
+ .${ClassName.DRAG_ROW_CONTROLS} {
704
707
  display: grid;
705
708
  align-items: center;
706
709
  position: absolute;
707
710
  left: -4px;
708
711
  z-index: ${akEditorUnitZIndex};
712
+
713
+ .${ClassName.DRAG_ROW_FLOATING_INSERT_DOT_WRAPPER} {
714
+ align-self: end;
715
+ position: absolute;
716
+ height: 100%;
717
+ width: 24px;
718
+ }
719
+
720
+ .${ClassName.DRAG_ROW_FLOATING_INSERT_DOT} {
721
+ position: absolute;
722
+ bottom: -3px;
723
+ left: 6px;
724
+ background-color: ${token(
725
+ 'color.background.accent.gray.subtler',
726
+ '#C1C7D0',
727
+ )};
728
+ height: 4px;
729
+ width: 4px;
730
+ border-radius: 50%;
731
+ }
732
+ }
733
+
734
+ .${ClassName.DRAG_COLUMN_CONTROLS} {
735
+ .${ClassName.COLUMN_CONTROLS_INNER} {
736
+ height: 24px;
737
+ position: absolute;
738
+ top: ${token('space.negative.150', '-12px')};
739
+ z-index: ${akEditorUnitZIndex};
740
+ }
741
+
742
+ .${ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT_WRAPPER} {
743
+ position: absolute;
744
+ height: 24px;
745
+ width: 100%;
746
+ }
747
+
748
+ .${ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT} {
749
+ background-color: ${token(
750
+ 'color.background.accent.gray.subtler',
751
+ '#C1C7D0',
752
+ )};
753
+ height: 4px;
754
+ width: 4px;
755
+ border-radius: 50%;
756
+ position: absolute;
757
+ right: -2px;
758
+ }
759
+ }
760
+
761
+ .${ClassName.CONTROLS_FLOATING_BUTTON_ROW}
762
+ .${ClassName.DRAG_CONTROLS_INSERT_BUTTON_INNER} {
763
+ bottom: -1px;
709
764
  }
710
765
 
711
766
  .${ClassName.DRAG_HANDLE_BUTTON_CONTAINER} {
@@ -719,10 +774,10 @@ export const tableStyles = (
719
774
  display: flex;
720
775
  justify-content: center;
721
776
  align-items: center;
777
+ outline: none !important;
722
778
 
723
779
  svg {
724
780
  rect {
725
- //
726
781
  fill: ${token('color.background.accent.gray.subtlest', '#F1F2F4')};
727
782
  }
728
783
  g {
@@ -149,3 +149,5 @@ export const TABLE_SNAP_GAP = 9;
149
149
  export const TABLE_HIGHLIGHT_GAP = 10;
150
150
  export const TABLE_HIGHLIGHT_TOLERANCE = 2;
151
151
  export const STICKY_HEADER_TOGGLE_TOLERANCE_MS = 5;
152
+
153
+ export const dragMenuDropdownWidth = 240;
@@ -180,6 +180,32 @@ const InsertButtonHover = () => css`
180
180
  }
181
181
  `;
182
182
 
183
+ export const dragInsertButtonWrapper = (props: ThemeProps) => css`
184
+ .${ClassName.DRAG_CONTROLS_INSERT_BUTTON_INNER} {
185
+ position: absolute;
186
+ z-index: ${akEditorUnitZIndex + 10};
187
+ bottom: -5px;
188
+ left: 3px;
189
+ }
190
+ .${ClassName.DRAG_CONTROLS_INSERT_BUTTON} {
191
+ ${Button(`
192
+ background: ${token('elevation.surface.overlay', 'white')};
193
+ color: ${token('color.icon', N300)};
194
+ border: 1px solid ${token(
195
+ 'color.background.accent.gray.subtler',
196
+ '#C1C7D0',
197
+ )};
198
+ border-radius: 50%;
199
+ `)}
200
+ }
201
+ .${ClassName.DRAG_CONTROLS_INSERT_BUTTON}:hover {
202
+ background: ${token('color.background.brand.bold', B300)};
203
+ border: 1px solid ${token('color.background.brand.bold', B300)};
204
+ color: ${token('color.icon.inverse', 'white')};
205
+ cursor: pointer;
206
+ }
207
+ `;
208
+
183
209
  export const insertColumnButtonWrapper = (props: ThemeProps) => css`
184
210
  ${InsertButton()}
185
211
  ${InsertButtonHover()}
@@ -388,7 +414,7 @@ export const floatingColumnControls = (props: ThemeProps) => {
388
414
  }
389
415
  }
390
416
 
391
- .${ClassName.COLUMN_CONTROLS_WITH_DRAG} {
417
+ .${ClassName.DRAG_COLUMN_CONTROLS} {
392
418
  box-sizing: border-box;
393
419
 
394
420
  .${ClassName.COLUMN_CONTROLS_INNER} {
@@ -40,10 +40,6 @@ export const isRowControlsButton = (node: HTMLElement | null): boolean =>
40
40
  containsClassName(node, ClassName.ROW_CONTROLS_BUTTON) ||
41
41
  containsClassName(node, ClassName.NUMBERED_COLUMN_BUTTON);
42
42
 
43
- export const isRowDragControlsButton = (node: HTMLElement | null) =>
44
- containsClassName(node, ClassName.ROW_CONTROLS_WITH_DRAG) ||
45
- closestElement(node, `.${ClassName.ROW_CONTROLS_WITH_DRAG}`);
46
-
47
43
  export const isResizeHandleDecoration = (node: HTMLElement | null): boolean =>
48
44
  containsClassName(node, ClassName.RESIZE_HANDLE_DECORATION);
49
45
 
@@ -55,6 +51,17 @@ export const isTableContainerOrWrapper = (node: HTMLElement | null): boolean =>
55
51
  containsClassName(node, ClassName.TABLE_CONTAINER) ||
56
52
  containsClassName(node, ClassName.TABLE_NODE_WRAPPER);
57
53
 
54
+ /** drag-and-drop classes */
55
+ export const isRowDragControlsButton = (node: HTMLElement | null) =>
56
+ containsClassName(node, ClassName.DRAG_ROW_CONTROLS) ||
57
+ closestElement(node, `.${ClassName.DRAG_ROW_CONTROLS}`);
58
+
59
+ export const isDragRowFloatingInsertDot = (node: HTMLElement | null) =>
60
+ containsClassName(node, ClassName.DRAG_ROW_FLOATING_INSERT_DOT_WRAPPER);
61
+
62
+ export const isDragColumnFloatingInsertDot = (node: HTMLElement | null) =>
63
+ containsClassName(node, ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT_WRAPPER);
64
+
58
65
  /*
59
66
  * This function returns which side of a given element the mouse cursor is,
60
67
  * using as a base the half of the width by default, for example: