@atlaskit/editor-plugin-table 5.3.1 → 5.3.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 (149) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/plugins/table/commands/hover.js +17 -8
  3. package/dist/cjs/plugins/table/commands/index.js +6 -0
  4. package/dist/cjs/plugins/table/commands/misc.js +1 -7
  5. package/dist/cjs/plugins/table/event-handlers.js +29 -2
  6. package/dist/cjs/plugins/table/index.js +1 -1
  7. package/dist/cjs/plugins/table/nodeviews/TableComponent.js +5 -3
  8. package/dist/cjs/plugins/table/nodeviews/table.js +4 -2
  9. package/dist/cjs/plugins/table/pm-plugins/decorations/plugin.js +7 -3
  10. package/dist/cjs/plugins/table/pm-plugins/decorations/utils/column-controls.js +7 -2
  11. package/dist/cjs/plugins/table/pm-plugins/default-table-selection.js +14 -1
  12. package/dist/cjs/plugins/table/pm-plugins/main.js +5 -5
  13. package/dist/cjs/plugins/table/reducer.js +2 -1
  14. package/dist/cjs/plugins/table/types.js +6 -0
  15. package/dist/cjs/plugins/table/ui/DragHandle/index.js +50 -0
  16. package/dist/cjs/plugins/table/ui/TableFloatingControls/NumberColumn/index.js +53 -14
  17. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/ClassicControls.js +114 -0
  18. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +53 -0
  19. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/index.js +11 -106
  20. package/dist/cjs/plugins/table/ui/TableFloatingControls/index.js +16 -6
  21. package/dist/cjs/plugins/table/ui/common-styles.js +9 -6
  22. package/dist/cjs/plugins/table/ui/consts.js +2 -1
  23. package/dist/cjs/plugins/table/ui/ui-styles.js +18 -9
  24. package/dist/cjs/plugins/table/utils/decoration.js +44 -18
  25. package/dist/cjs/plugins/table/utils/dom.js +7 -1
  26. package/dist/cjs/plugins/table/utils/index.js +12 -0
  27. package/dist/es2019/plugins/table/commands/hover.js +12 -8
  28. package/dist/es2019/plugins/table/commands/index.js +1 -1
  29. package/dist/es2019/plugins/table/commands/misc.js +1 -7
  30. package/dist/es2019/plugins/table/event-handlers.js +28 -2
  31. package/dist/es2019/plugins/table/index.js +1 -1
  32. package/dist/es2019/plugins/table/nodeviews/TableComponent.js +5 -3
  33. package/dist/es2019/plugins/table/nodeviews/table.js +4 -2
  34. package/dist/es2019/plugins/table/pm-plugins/decorations/plugin.js +8 -6
  35. package/dist/es2019/plugins/table/pm-plugins/decorations/utils/column-controls.js +7 -2
  36. package/dist/es2019/plugins/table/pm-plugins/default-table-selection.js +13 -0
  37. package/dist/es2019/plugins/table/pm-plugins/main.js +6 -5
  38. package/dist/es2019/plugins/table/reducer.js +2 -1
  39. package/dist/es2019/plugins/table/types.js +6 -0
  40. package/dist/es2019/plugins/table/ui/DragHandle/index.js +41 -0
  41. package/dist/es2019/plugins/table/ui/TableFloatingControls/NumberColumn/index.js +54 -10
  42. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/ClassicControls.js +86 -0
  43. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +43 -0
  44. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/index.js +2 -88
  45. package/dist/es2019/plugins/table/ui/TableFloatingControls/index.js +17 -7
  46. package/dist/es2019/plugins/table/ui/common-styles.js +47 -12
  47. package/dist/es2019/plugins/table/ui/consts.js +1 -0
  48. package/dist/es2019/plugins/table/ui/ui-styles.js +57 -14
  49. package/dist/es2019/plugins/table/utils/decoration.js +44 -18
  50. package/dist/es2019/plugins/table/utils/dom.js +2 -0
  51. package/dist/es2019/plugins/table/utils/index.js +1 -1
  52. package/dist/esm/plugins/table/commands/hover.js +16 -8
  53. package/dist/esm/plugins/table/commands/index.js +1 -1
  54. package/dist/esm/plugins/table/commands/misc.js +1 -7
  55. package/dist/esm/plugins/table/event-handlers.js +29 -2
  56. package/dist/esm/plugins/table/index.js +1 -1
  57. package/dist/esm/plugins/table/nodeviews/TableComponent.js +5 -3
  58. package/dist/esm/plugins/table/nodeviews/table.js +4 -2
  59. package/dist/esm/plugins/table/pm-plugins/decorations/plugin.js +8 -6
  60. package/dist/esm/plugins/table/pm-plugins/decorations/utils/column-controls.js +7 -2
  61. package/dist/esm/plugins/table/pm-plugins/default-table-selection.js +13 -0
  62. package/dist/esm/plugins/table/pm-plugins/main.js +7 -7
  63. package/dist/esm/plugins/table/reducer.js +2 -1
  64. package/dist/esm/plugins/table/types.js +6 -0
  65. package/dist/esm/plugins/table/ui/DragHandle/index.js +41 -0
  66. package/dist/esm/plugins/table/ui/TableFloatingControls/NumberColumn/index.js +54 -15
  67. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/ClassicControls.js +104 -0
  68. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +46 -0
  69. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/index.js +2 -104
  70. package/dist/esm/plugins/table/ui/TableFloatingControls/index.js +17 -7
  71. package/dist/esm/plugins/table/ui/common-styles.js +10 -7
  72. package/dist/esm/plugins/table/ui/consts.js +1 -0
  73. package/dist/esm/plugins/table/ui/ui-styles.js +18 -9
  74. package/dist/esm/plugins/table/utils/decoration.js +44 -18
  75. package/dist/esm/plugins/table/utils/dom.js +6 -0
  76. package/dist/esm/plugins/table/utils/index.js +1 -1
  77. package/dist/types/plugins/table/commands/hover.d.ts +2 -1
  78. package/dist/types/plugins/table/commands/index.d.ts +1 -1
  79. package/dist/types/plugins/table/event-handlers.d.ts +1 -0
  80. package/dist/types/plugins/table/nodeviews/types.d.ts +4 -3
  81. package/dist/types/plugins/table/pm-plugins/decorations/plugin.d.ts +2 -1
  82. package/dist/types/plugins/table/pm-plugins/decorations/utils/column-controls.d.ts +1 -1
  83. package/dist/types/plugins/table/pm-plugins/default-table-selection.d.ts +12 -0
  84. package/dist/types/plugins/table/pm-plugins/main.d.ts +1 -1
  85. package/dist/types/plugins/table/types.d.ts +16 -1
  86. package/dist/types/plugins/table/ui/DragHandle/index.d.ts +11 -0
  87. package/dist/types/plugins/table/ui/TableFloatingControls/NumberColumn/index.d.ts +4 -1
  88. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/ClassicControls.d.ts +17 -0
  89. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +16 -0
  90. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/index.d.ts +2 -17
  91. package/dist/types/plugins/table/ui/TableFloatingControls/index.d.ts +3 -2
  92. package/dist/types/plugins/table/ui/consts.d.ts +1 -0
  93. package/dist/types/plugins/table/utils/decoration.d.ts +2 -2
  94. package/dist/types/plugins/table/utils/dom.d.ts +2 -0
  95. package/dist/types/plugins/table/utils/index.d.ts +1 -1
  96. package/dist/types-ts4.5/plugins/table/commands/hover.d.ts +2 -1
  97. package/dist/types-ts4.5/plugins/table/commands/index.d.ts +1 -1
  98. package/dist/types-ts4.5/plugins/table/event-handlers.d.ts +1 -0
  99. package/dist/types-ts4.5/plugins/table/nodeviews/types.d.ts +4 -3
  100. package/dist/types-ts4.5/plugins/table/pm-plugins/decorations/plugin.d.ts +2 -1
  101. package/dist/types-ts4.5/plugins/table/pm-plugins/decorations/utils/column-controls.d.ts +1 -1
  102. package/dist/types-ts4.5/plugins/table/pm-plugins/default-table-selection.d.ts +12 -0
  103. package/dist/types-ts4.5/plugins/table/pm-plugins/main.d.ts +1 -1
  104. package/dist/types-ts4.5/plugins/table/types.d.ts +16 -1
  105. package/dist/types-ts4.5/plugins/table/ui/DragHandle/index.d.ts +11 -0
  106. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/NumberColumn/index.d.ts +4 -1
  107. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/ClassicControls.d.ts +17 -0
  108. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +16 -0
  109. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/index.d.ts +2 -17
  110. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/index.d.ts +3 -2
  111. package/dist/types-ts4.5/plugins/table/ui/consts.d.ts +1 -0
  112. package/dist/types-ts4.5/plugins/table/utils/decoration.d.ts +2 -2
  113. package/dist/types-ts4.5/plugins/table/utils/dom.d.ts +2 -0
  114. package/dist/types-ts4.5/plugins/table/utils/index.d.ts +1 -1
  115. package/package.json +3 -2
  116. package/src/__tests__/unit/event-handlers.ts +74 -1
  117. package/src/__tests__/unit/pm-plugins/decorations/column-controls.ts +35 -15
  118. package/src/__tests__/unit/pm-plugins/decorations/plugin.ts +146 -42
  119. package/src/__tests__/unit/ui/NumberColumn.tsx +148 -0
  120. package/src/__tests__/unit/ui/RowControls.tsx +4 -4
  121. package/src/__tests__/unit/ui/RowDragControls.tsx +118 -0
  122. package/src/__tests__/unit/ui/TableFloatingControls.tsx +9 -5
  123. package/src/plugins/table/commands/hover.ts +16 -7
  124. package/src/plugins/table/commands/index.ts +1 -0
  125. package/src/plugins/table/commands/misc.ts +0 -5
  126. package/src/plugins/table/event-handlers.ts +49 -2
  127. package/src/plugins/table/index.tsx +1 -1
  128. package/src/plugins/table/nodeviews/TableComponent.tsx +3 -2
  129. package/src/plugins/table/nodeviews/table.tsx +2 -0
  130. package/src/plugins/table/nodeviews/types.ts +4 -3
  131. package/src/plugins/table/pm-plugins/decorations/plugin.ts +13 -4
  132. package/src/plugins/table/pm-plugins/decorations/utils/column-controls.ts +10 -5
  133. package/src/plugins/table/pm-plugins/default-table-selection.ts +10 -0
  134. package/src/plugins/table/pm-plugins/main.ts +9 -4
  135. package/src/plugins/table/reducer.ts +2 -1
  136. package/src/plugins/table/types.ts +14 -2
  137. package/src/plugins/table/ui/DragHandle/index.tsx +57 -0
  138. package/src/plugins/table/ui/TableFloatingControls/NumberColumn/index.tsx +68 -30
  139. package/src/plugins/table/ui/TableFloatingControls/RowControls/ClassicControls.tsx +129 -0
  140. package/src/plugins/table/ui/TableFloatingControls/RowControls/DragControls.tsx +75 -0
  141. package/src/plugins/table/ui/TableFloatingControls/RowControls/index.tsx +2 -135
  142. package/src/plugins/table/ui/TableFloatingControls/index.tsx +43 -24
  143. package/src/plugins/table/ui/common-styles.ts +52 -11
  144. package/src/plugins/table/ui/consts.ts +1 -0
  145. package/src/plugins/table/ui/ui-styles.ts +58 -14
  146. package/src/plugins/table/utils/decoration.ts +75 -27
  147. package/src/plugins/table/utils/dom.ts +8 -0
  148. package/src/plugins/table/utils/index.ts +2 -0
  149. package/tsconfig.app.json +3 -0
@@ -33,6 +33,7 @@ import {
33
33
  clearHoverSelection,
34
34
  hideInsertColumnOrRowButton,
35
35
  hideResizeHandleLine,
36
+ hoverCell,
36
37
  hoverColumns,
37
38
  selectColumn,
38
39
  setEditorFocus,
@@ -275,14 +276,21 @@ export const handleMouseLeave = (view: EditorView, event: Event): boolean => {
275
276
  }
276
277
 
277
278
  const { state, dispatch } = view;
278
- const { insertColumnButtonIndex, insertRowButtonIndex } =
279
- getPluginState(state);
279
+ const {
280
+ insertColumnButtonIndex,
281
+ insertRowButtonIndex,
282
+ isDragAndDropEnabled,
283
+ } = getPluginState(state);
280
284
 
281
285
  const target = event.target;
282
286
  if (isTableControlsButton(target)) {
283
287
  return true;
284
288
  }
285
289
 
290
+ if (isDragAndDropEnabled) {
291
+ hoverCell(undefined, undefined)(state, dispatch);
292
+ }
293
+
286
294
  if (
287
295
  (typeof insertColumnButtonIndex !== 'undefined' ||
288
296
  typeof insertRowButtonIndex !== 'undefined') &&
@@ -498,3 +506,42 @@ export const whenTableInFocus =
498
506
 
499
507
  return eventHandler(view, mouseEvent, elementContentRects);
500
508
  };
509
+
510
+ const trackCellLocation = (view: EditorView, mouseEvent: Event) => {
511
+ const target = mouseEvent.target;
512
+ const maybeTableCell = isElementInTableCell(
513
+ target as HTMLElement,
514
+ ) as HTMLTableCellElement | null;
515
+
516
+ if (!maybeTableCell) {
517
+ return;
518
+ }
519
+
520
+ const colIndex = maybeTableCell.cellIndex;
521
+ const rowElement = closestElement(
522
+ target as HTMLElement,
523
+ 'tr',
524
+ ) as HTMLTableRowElement;
525
+ const rowIndex = rowElement && rowElement.rowIndex;
526
+ const { hoveredCell } = getPluginState(view.state);
527
+
528
+ if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== rowIndex) {
529
+ hoverCell(rowIndex, colIndex)(view.state, view.dispatch);
530
+ }
531
+ };
532
+
533
+ export const withCellTracking =
534
+ (
535
+ eventHandler: (
536
+ view: EditorView,
537
+ mouseEvent: Event,
538
+ elementContentRects?: ElementContentRects,
539
+ ) => boolean,
540
+ elementContentRects?: ElementContentRects,
541
+ ) =>
542
+ (view: EditorView, mouseEvent: Event): boolean => {
543
+ if (getPluginState(view.state).isDragAndDropEnabled) {
544
+ trackCellLocation(view, mouseEvent);
545
+ }
546
+ return eventHandler(view, mouseEvent, elementContentRects);
547
+ };
@@ -196,8 +196,8 @@ const tablesPlugin: TablePlugin = ({ config: options, api }) => {
196
196
  getEditorFeatureFlags || defaultGetEditorFeatureFlags,
197
197
  getIntl,
198
198
  breakoutEnabled,
199
- fullWidthEnabled,
200
199
  tableResizingEnabled,
200
+ fullWidthEnabled,
201
201
  wasFullWidthEnabled,
202
202
  dragAndDropEnabled,
203
203
  editorAnalyticsAPI,
@@ -403,7 +403,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
403
403
  const { showBeforeShadow, showAfterShadow } = this.state;
404
404
  const node = getNode();
405
405
  // doesn't work well with WithPluginState
406
- const { isInDanger, hoveredRows } = getPluginState(view.state);
406
+ const { isInDanger, hoveredRows, hoveredCell } = getPluginState(view.state);
407
407
 
408
408
  const tableRef = this.table || undefined;
409
409
  const headerRow = tableRef
@@ -418,10 +418,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
418
418
  tableRef={tableRef}
419
419
  tableActive={tableActive}
420
420
  hoveredRows={hoveredRows}
421
+ hoveredCell={hoveredCell}
421
422
  isInDanger={isInDanger}
422
423
  isResizing={isResizing}
423
424
  isNumberColumnEnabled={node.attrs.isNumberColumnEnabled}
424
425
  isHeaderRowEnabled={isHeaderRowEnabled}
426
+ isDragAndDropEnabled={options?.isDragAndDropEnabled}
425
427
  ordering={ordering}
426
428
  isHeaderColumnEnabled={isHeaderColumnEnabled}
427
429
  hasHeaderRow={hasHeaderRow}
@@ -429,7 +431,6 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
429
431
  selection={view.state.selection}
430
432
  headerRowHeight={headerRow ? headerRow.offsetHeight : undefined}
431
433
  stickyHeader={this.state.stickyHeader}
432
- getEditorFeatureFlags={this.props.getEditorFeatureFlags}
433
434
  />
434
435
  </div>
435
436
  );
@@ -352,6 +352,7 @@ export const createTableView = (
352
352
  isFullWidthModeEnabled,
353
353
  wasFullWidthModeEnabled,
354
354
  isTableResizingEnabled,
355
+ isDragAndDropEnabled,
355
356
  } = getPluginState(view.state);
356
357
  const { allowColumnResizing } = getPluginConfig(pluginConfig);
357
358
  const hasIntlContext = true;
@@ -368,6 +369,7 @@ export const createTableView = (
368
369
  isFullWidthModeEnabled,
369
370
  wasFullWidthModeEnabled,
370
371
  isTableResizingEnabled,
372
+ isDragAndDropEnabled,
371
373
  },
372
374
  getEditorContainerWidth,
373
375
  getEditorFeatureFlags,
@@ -1,11 +1,11 @@
1
- import { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
1
+ import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
2
2
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal-provider';
3
3
  import type {
4
4
  GetEditorContainerWidth,
5
5
  GetEditorFeatureFlags,
6
6
  } from '@atlaskit/editor-common/types';
7
- import { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
8
- import { EditorView } from '@atlaskit/editor-prosemirror/view';
7
+ import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
8
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
9
9
 
10
10
  import type { PluginInjectionAPI } from '../types';
11
11
 
@@ -14,6 +14,7 @@ export type TableOptions = {
14
14
  isFullWidthModeEnabled?: boolean;
15
15
  wasFullWidthModeEnabled?: boolean;
16
16
  isTableResizingEnabled?: boolean;
17
+ isDragAndDropEnabled?: boolean;
17
18
  };
18
19
 
19
20
  export interface Props {
@@ -1,11 +1,11 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
- import {
2
+ import type {
3
3
  EditorState,
4
- PluginKey,
5
4
  // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
6
5
  ReadonlyTransaction,
7
6
  Transaction,
8
7
  } from '@atlaskit/editor-prosemirror/state';
8
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
9
9
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
10
10
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
11
11
 
@@ -30,6 +30,7 @@ export const handleDocOrSelectionChanged = (
30
30
  ): DecorationSet => {
31
31
  const isResizing = tableWidthPluginKey.getState(newState)?.resizing;
32
32
  const wasResizing = tableWidthPluginKey.getState(oldState)?.resizing;
33
+
33
34
  const changedResizing = isResizing !== wasResizing;
34
35
 
35
36
  // Remove column controls when resizing
@@ -38,7 +39,8 @@ export const handleDocOrSelectionChanged = (
38
39
  } else if (
39
40
  tr.docChanged ||
40
41
  tr.selection instanceof CellSelection ||
41
- changedResizing
42
+ changedResizing ||
43
+ tr.getMeta(tablePluginKey)?.type === 'HOVER_CELL'
42
44
  ) {
43
45
  return buildColumnControlsDecorations({
44
46
  decorationSet,
@@ -69,6 +71,12 @@ export const createPlugin = () => {
69
71
  apply: (tr, decorationSet, oldState, newState) => {
70
72
  let pluginState = decorationSet;
71
73
  const meta = tr.getMeta(tablePluginKey);
74
+ const previousHover = tablePluginKey.getState(oldState)?.hoveredCell;
75
+ const newHover = tablePluginKey.getState(newState)?.hoveredCell;
76
+ const changedCellHover =
77
+ previousHover?.colIndex !== newHover?.colIndex ||
78
+ previousHover?.rowIndex !== newHover?.rowIndex;
79
+
72
80
  if (meta && meta.data && meta.data.decorationSet) {
73
81
  pluginState = meta.data.decorationSet;
74
82
  }
@@ -76,7 +84,8 @@ export const createPlugin = () => {
76
84
  if (
77
85
  tr.docChanged ||
78
86
  tr.selectionSet ||
79
- tr.getMeta(tableWidthPluginKey)
87
+ tr.getMeta(tableWidthPluginKey) ||
88
+ changedCellHover
80
89
  ) {
81
90
  pluginState = pluginState.map(tr.mapping, tr.doc);
82
91
  return handleDocOrSelectionChanged(
@@ -1,9 +1,9 @@
1
1
  // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
2
- import {
2
+ import type {
3
3
  ReadonlyTransaction,
4
4
  Transaction,
5
5
  } from '@atlaskit/editor-prosemirror/state';
6
- import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
7
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
8
8
  import { findTable } from '@atlaskit/editor-tables/utils';
9
9
 
@@ -15,9 +15,10 @@ import {
15
15
  findControlsHoverDecoration,
16
16
  updateDecorations,
17
17
  } from '../../../utils/decoration';
18
+ import { pluginKey as tablePluginKey } from '../../plugin-key';
18
19
 
19
20
  import { composeDecorations } from './compose-decorations';
20
- import { DecorationTransformer } from './types';
21
+ import type { DecorationTransformer } from './types';
21
22
 
22
23
  const isColumnSelected = (tr: Transaction | ReadonlyTransaction): boolean =>
23
24
  tr.selection instanceof CellSelection && tr.selection.isColSelection();
@@ -49,13 +50,17 @@ const maybeUpdateColumnControlsDecoration: DecorationTransformer = ({
49
50
  tr,
50
51
  }): DecorationSet => {
51
52
  const table = findTable(tr.selection);
52
- if (!table) {
53
+ const meta = tr.getMeta(tablePluginKey);
54
+
55
+ // avoid re-drawing state if dnd decorations don't need to be updated
56
+ if (!table && meta?.type !== 'HOVER_CELL') {
53
57
  return decorationSet;
54
58
  }
59
+
55
60
  return updateDecorations(
56
61
  tr.doc,
57
62
  decorationSet,
58
- createColumnControlsDecoration(tr.selection),
63
+ createColumnControlsDecoration(tr.selection, meta?.data?.hoveredCell),
59
64
  TableDecorations.COLUMN_CONTROLS_DECORATIONS,
60
65
  );
61
66
  };
@@ -2,3 +2,13 @@ export const defaultTableSelection = {
2
2
  hoveredColumns: [],
3
3
  hoveredRows: [],
4
4
  };
5
+
6
+ /**
7
+ * Creating a separate object for hoveredCell so it doesn't get defaulted when `handleDocOrSelectionChanged` runs.
8
+ *
9
+ * It is safe to persist this value as it gets removed when the mouse cursor leaves the table, so no need to remove it
10
+ * when doc changes.
11
+ */
12
+ export const defaultHoveredCell = {
13
+ hoveredCell: { rowIndex: undefined, colIndex: undefined },
14
+ };
@@ -63,6 +63,7 @@ import {
63
63
  handleMouseOver,
64
64
  handleTripleClick,
65
65
  whenTableInFocus,
66
+ withCellTracking,
66
67
  } from '../event-handlers';
67
68
  import { createTableView } from '../nodeviews/table';
68
69
  import TableCell from '../nodeviews/TableCell';
@@ -85,7 +86,10 @@ import {
85
86
  } from '../utils';
86
87
  import { isHeaderRowRequired } from '../utils/paste';
87
88
 
88
- import { defaultTableSelection } from './default-table-selection';
89
+ import {
90
+ defaultHoveredCell,
91
+ defaultTableSelection,
92
+ } from './default-table-selection';
89
93
  import { createPluginState, getPluginState } from './plugin-factory';
90
94
  import { pluginKey } from './plugin-key';
91
95
 
@@ -99,8 +103,8 @@ export const createPlugin = (
99
103
  getEditorFeatureFlags: GetEditorFeatureFlags,
100
104
  getIntl: () => IntlShape,
101
105
  breakoutEnabled?: boolean,
102
- fullWidthModeEnabled?: boolean,
103
106
  tableResizingEnabled?: boolean,
107
+ fullWidthModeEnabled?: boolean,
104
108
  previousFullWidthModeEnabled?: boolean,
105
109
  dragAndDropEnabled?: boolean,
106
110
  editorAnalyticsAPI?: EditorAnalyticsAPI,
@@ -117,6 +121,7 @@ export const createPlugin = (
117
121
  isHeaderRowEnabled: !!pluginConfig.allowHeaderRow,
118
122
  isHeaderColumnEnabled: false,
119
123
  isDragAndDropEnabled: dragAndDropEnabled,
124
+ ...defaultHoveredCell,
120
125
  ...defaultTableSelection,
121
126
  getIntl,
122
127
  });
@@ -375,8 +380,8 @@ export const createPlugin = (
375
380
  handleDOMEvents: {
376
381
  focus: handleFocus,
377
382
  blur: handleBlur,
378
- mousedown: handleMouseDown,
379
- mouseover: whenTableInFocus(handleMouseOver),
383
+ mousedown: withCellTracking(handleMouseDown),
384
+ mouseover: whenTableInFocus(withCellTracking(handleMouseOver)),
380
385
  mouseleave: whenTableInFocus(handleMouseLeave),
381
386
  mouseout: whenTableInFocus(handleMouseOut),
382
387
  mousemove: whenTableInFocus(handleMouseMove, elementContentRects),
@@ -145,7 +145,8 @@ export default (
145
145
  case 'HOVER_ROWS':
146
146
  case 'HOVER_COLUMNS':
147
147
  case 'HOVER_TABLE':
148
- case 'HOVER_CELLS':
148
+ case 'HOVER_MERGED_CELLS':
149
+ case 'HOVER_CELL':
149
150
  case 'SHOW_RESIZE_HANDLE_LINE':
150
151
  case 'SET_EDITOR_FOCUS':
151
152
  return { ...pluginState, ...action.data };
@@ -86,10 +86,13 @@ export type { ColumnResizingPluginState } from '@atlaskit/editor-common/types';
86
86
  */
87
87
  export type CellColumnPositioning = Pick<Rect, 'right' | 'left'>;
88
88
 
89
+ export type CellHoverCoordinates = { colIndex?: number; rowIndex?: number };
90
+
89
91
  export interface TablePluginState {
90
92
  editorHasFocus?: boolean;
91
93
  hoveredColumns: number[];
92
94
  hoveredRows: number[];
95
+ hoveredCell: CellHoverCoordinates;
93
96
  pluginConfig: PluginConfig;
94
97
  isHeaderColumnEnabled: boolean;
95
98
  isHeaderRowEnabled: boolean;
@@ -122,7 +125,6 @@ export interface TablePluginState {
122
125
  isBreakoutEnabled?: boolean;
123
126
  wasFullWidthModeEnabled?: boolean;
124
127
  isTableResizingEnabled?: boolean;
125
-
126
128
  isDragAndDropEnabled?: boolean;
127
129
  }
128
130
 
@@ -151,7 +153,7 @@ export type TablePluginAction =
151
153
  };
152
154
  }
153
155
  | {
154
- type: 'HOVER_CELLS';
156
+ type: 'HOVER_MERGED_CELLS';
155
157
  data: {
156
158
  decorationSet: DecorationSet;
157
159
  };
@@ -198,6 +200,7 @@ export type TablePluginAction =
198
200
  | { type: 'CLEAR_HOVER_SELECTION'; data: { decorationSet: DecorationSet } }
199
201
  | { type: 'SHOW_RESIZE_HANDLE_LINE'; data: { decorationSet: DecorationSet } }
200
202
  | { type: 'HIDE_RESIZE_HANDLE_LINE'; data: { decorationSet: DecorationSet } }
203
+ | { type: 'HOVER_CELL'; data: CellHoverCoordinates }
201
204
  | { type: 'SET_TARGET_CELL_POSITION'; data: { targetCellPosition?: number } }
202
205
  | {
203
206
  type: 'SELECT_COLUMN';
@@ -233,6 +236,7 @@ export type ColumnResizingPluginAction =
233
236
  };
234
237
 
235
238
  export enum TableDecorations {
239
+ /** Classic controls */
236
240
  ALL_CONTROLS_HOVER = 'CONTROLS_HOVER',
237
241
  ROW_CONTROLS_HOVER = 'ROW_CONTROLS_HOVER',
238
242
  COLUMN_CONTROLS_HOVER = 'COLUMN_CONTROLS_HOVER',
@@ -255,6 +259,7 @@ export enum TableDecorations {
255
259
  export const TableCssClassName = {
256
260
  ...TableSharedCssClassName,
257
261
 
262
+ /** Classic controls */
258
263
  COLUMN_CONTROLS: `${tablePrefixSelector}-column-controls`,
259
264
  COLUMN_CONTROLS_DECORATIONS: `${tablePrefixSelector}-column-controls-decoration`,
260
265
  COLUMN_SELECTED: `${tablePrefixSelector}-column__selected`,
@@ -293,8 +298,15 @@ export const TableCssClassName = {
293
298
  CORNER_CONTROLS_INSERT_COLUMN_MARKER: `${tablePrefixSelector}-corner-controls__insert-column-marker`,
294
299
  CONTROLS_CORNER_BUTTON: `${tablePrefixSelector}-corner-button`,
295
300
 
301
+ /** Controls with drag handle */
302
+ COLUMN_CONTROLS_DECORATIONS_WITH_DRAG: `${tablePrefixSelector}-column-controls-decoration-with-drag`,
303
+
304
+ ROW_CONTROLS_WITH_DRAG: `${tablePrefixSelector}-row-controls-with-drag`,
305
+
306
+ /** Other classes */
296
307
  NUMBERED_COLUMN: `${tablePrefixSelector}-numbered-column`,
297
308
  NUMBERED_COLUMN_BUTTON: `${tablePrefixSelector}-numbered-column__button`,
309
+ NUMBERED_COLUMN_BUTTON_DISABLED: `${tablePrefixSelector}-numbered-column__button-disabled`,
298
310
 
299
311
  HOVERED_COLUMN: `${tablePrefixSelector}-hovered-column`,
300
312
  HOVERED_ROW: `${tablePrefixSelector}-hovered-row`,
@@ -0,0 +1,57 @@
1
+ import type { MouseEventHandler } from 'react';
2
+ import React, { useEffect, useRef } from 'react';
3
+
4
+ import { DragHandleButton } from '@atlaskit/pragmatic-drag-and-drop-react-accessibility/drag-handle-button';
5
+ import { draggable } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
6
+ import { token } from '@atlaskit/tokens';
7
+
8
+ type DragHandleProps = {
9
+ tableLocalId: string;
10
+ indexes: number[];
11
+ direction?: 'column' | 'row';
12
+ onClick?: MouseEventHandler;
13
+ onMouseOver?: MouseEventHandler;
14
+ onMouseOut?: MouseEventHandler;
15
+ };
16
+
17
+ // TODO: use for now, in future replace with custom @atlaskit/icon/glyph/drag-handler
18
+ // width is too large (24px), should be 16px
19
+ export const DragHandle = ({
20
+ tableLocalId,
21
+ direction = 'row',
22
+ indexes,
23
+ onClick,
24
+ onMouseOver,
25
+ onMouseOut,
26
+ }: DragHandleProps) => {
27
+ const dragHandleDivRef = useRef<HTMLDivElement>(null);
28
+
29
+ useEffect(() => {
30
+ const dragHandleDivRefCurrent = dragHandleDivRef.current;
31
+ if (dragHandleDivRefCurrent) {
32
+ return draggable({
33
+ element: dragHandleDivRefCurrent,
34
+ getInitialData() {
35
+ return {
36
+ localId: tableLocalId,
37
+ type: `table-${direction}`,
38
+ indexes,
39
+ };
40
+ },
41
+ });
42
+ }
43
+ }, [tableLocalId, direction, indexes]);
44
+ return (
45
+ <div
46
+ ref={dragHandleDivRef}
47
+ style={{
48
+ backgroundColor: `${token('elevation.surface', 'white')}`,
49
+ borderRadius: '4px',
50
+ border: `2px solid ${token('elevation.surface', 'white')}`,
51
+ transform: direction === 'column' ? 'rotate(90deg)' : 'none',
52
+ }}
53
+ >
54
+ <DragHandleButton label="blah" />
55
+ </div>
56
+ );
57
+ };
@@ -1,12 +1,16 @@
1
1
  import React, { Component } from 'react';
2
2
 
3
+ import classnames from 'classnames';
4
+
3
5
  import { Selection } from '@atlaskit/editor-prosemirror/state';
4
- import { EditorView } from '@atlaskit/editor-prosemirror/view';
6
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
7
  import { isRowSelected } from '@atlaskit/editor-tables/utils';
6
8
 
7
- import { clearHoverSelection } from '../../../commands';
9
+ import { clearHoverSelection, hoverCell } from '../../../commands';
10
+ import { getPluginState } from '../../../pm-plugins/plugin-factory';
8
11
  import { TableCssClassName as ClassName } from '../../../types';
9
12
  import { getRowHeights } from '../../../utils';
13
+ import { tableBorderColor } from '../../consts';
10
14
 
11
15
  export interface Props {
12
16
  editorView: EditorView;
@@ -19,11 +23,13 @@ export interface Props {
19
23
  isInDanger?: boolean;
20
24
  isResizing?: boolean;
21
25
  stickyTop?: number;
26
+ isDragAndDropEnabled?: boolean;
22
27
  }
23
28
 
24
29
  export default class NumberColumn extends Component<Props, any> {
25
30
  render() {
26
- const { tableRef, hasHeaderRow } = this.props;
31
+ const { tableRef, hasHeaderRow, isDragAndDropEnabled, tableActive } =
32
+ this.props;
27
33
  const rowHeights = getRowHeights(tableRef);
28
34
 
29
35
  return (
@@ -34,30 +40,38 @@ export default class NumberColumn extends Component<Props, any> {
34
40
  hasHeaderRow && this.props.stickyTop !== undefined
35
41
  ? rowHeights[0]
36
42
  : undefined,
43
+ borderLeft:
44
+ isDragAndDropEnabled && tableActive
45
+ ? `1px solid ${tableBorderColor()}`
46
+ : undefined,
37
47
  }}
38
48
  contentEditable={false}
39
49
  >
40
- {rowHeights.map((rowHeight, index) => (
41
- <div
42
- key={`wrapper-${index}`}
43
- className={this.getClassNames(index)}
44
- data-index={index}
45
- style={{
46
- height: rowHeight,
47
- top:
48
- this.props.stickyTop !== undefined &&
49
- hasHeaderRow &&
50
- index === 0
51
- ? `${this.props.stickyTop}px`
52
- : undefined,
53
- }}
54
- onClick={(event) => this.selectRow(index, event)}
55
- onMouseOver={() => this.hoverRows(index)}
56
- onMouseOut={this.clearHoverSelection}
57
- >
58
- {hasHeaderRow ? (index > 0 ? index : null) : index + 1}
59
- </div>
60
- ))}
50
+ {rowHeights.map((rowHeight, index) =>
51
+ isDragAndDropEnabled ? (
52
+ <div
53
+ key={`wrapper-${index}`}
54
+ className={this.getClassNames(index, true)}
55
+ data-index={index}
56
+ style={this.getCellStyles(index, rowHeight)}
57
+ onMouseOver={() => this.updateDragHandleLocation(index)}
58
+ >
59
+ {hasHeaderRow ? (index > 0 ? index : null) : index + 1}
60
+ </div>
61
+ ) : (
62
+ <div
63
+ key={`wrapper-${index}`}
64
+ className={this.getClassNames(index)}
65
+ data-index={index}
66
+ style={this.getCellStyles(index, rowHeight)}
67
+ onClick={(event) => this.selectRow(index, event)}
68
+ onMouseOver={() => this.hoverRows(index)}
69
+ onMouseOut={this.clearHoverSelection}
70
+ >
71
+ {hasHeaderRow ? (index > 0 ? index : null) : index + 1}
72
+ </div>
73
+ ),
74
+ )}
61
75
  </div>
62
76
  );
63
77
  }
@@ -95,15 +109,39 @@ export default class NumberColumn extends Component<Props, any> {
95
109
  }
96
110
  };
97
111
 
98
- private getClassNames = (index: number) => {
112
+ private updateDragHandleLocation = (rowIndex: number) => {
113
+ const { editorView, tableActive } = this.props;
114
+ const { state, dispatch } = editorView;
115
+ const { hoveredCell } = getPluginState(state);
116
+
117
+ if (tableActive && hoveredCell.rowIndex !== rowIndex) {
118
+ hoverCell(rowIndex, hoveredCell.colIndex)(state, dispatch);
119
+ }
120
+ };
121
+
122
+ private getCellStyles = (index: number, rowHeight: number) => {
123
+ const { stickyTop, hasHeaderRow } = this.props;
124
+ if (stickyTop && hasHeaderRow && index === 0) {
125
+ return {
126
+ height: rowHeight,
127
+ top: `${stickyTop}px`,
128
+ };
129
+ }
130
+ return {
131
+ height: rowHeight,
132
+ };
133
+ };
134
+
135
+ private getClassNames = (index: number, isButtonDisabled = false) => {
99
136
  const { hoveredRows, editorView, isInDanger, isResizing } = this.props;
100
137
  const isActive =
101
138
  isRowSelected(index)(editorView.state.selection) ||
102
139
  ((hoveredRows || []).indexOf(index) !== -1 && !isResizing);
103
- return [
104
- ClassName.NUMBERED_COLUMN_BUTTON,
105
- isActive ? ClassName.HOVERED_CELL_ACTIVE : '',
106
- isActive && isInDanger ? ClassName.HOVERED_CELL_IN_DANGER : '',
107
- ].join(' ');
140
+
141
+ return classnames(ClassName.NUMBERED_COLUMN_BUTTON, {
142
+ [ClassName.NUMBERED_COLUMN_BUTTON_DISABLED]: isButtonDisabled,
143
+ [ClassName.HOVERED_CELL_IN_DANGER]: isActive && isInDanger,
144
+ [ClassName.HOVERED_CELL_ACTIVE]: isActive,
145
+ });
108
146
  };
109
147
  }