@atlaskit/editor-plugin-table 5.2.2 → 5.3.1

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 (112) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/plugins/table/nodeviews/TableComponent.js +20 -2
  3. package/dist/cjs/plugins/table/nodeviews/table.js +1 -0
  4. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/commands.js +36 -7
  5. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/handlers.js +24 -0
  6. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/plugin-factory.js +29 -4
  7. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/plugin.js +83 -9
  8. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/reducer.js +2 -0
  9. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/utils/index.js +12 -0
  10. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/utils/monitor.js +59 -0
  11. package/dist/cjs/plugins/table/types.js +12 -1
  12. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/ColumnDropTargets/index.js +106 -0
  13. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/index.js +90 -0
  14. package/dist/cjs/plugins/table/ui/common-styles.js +1 -1
  15. package/dist/cjs/plugins/table/ui/consts.js +2 -1
  16. package/dist/cjs/plugins/table/ui/ui-styles.js +15 -9
  17. package/dist/cjs/plugins/table/utils/decoration.js +67 -1
  18. package/dist/cjs/plugins/table/utils/index.js +26 -1
  19. package/dist/cjs/plugins/table/utils/merged-cells.js +66 -0
  20. package/dist/es2019/plugins/table/nodeviews/TableComponent.js +20 -2
  21. package/dist/es2019/plugins/table/nodeviews/table.js +1 -0
  22. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/commands.js +35 -7
  23. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/handlers.js +10 -0
  24. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/plugin-factory.js +28 -4
  25. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/plugin.js +82 -6
  26. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/reducer.js +2 -0
  27. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/utils/index.js +1 -0
  28. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/utils/monitor.js +56 -0
  29. package/dist/es2019/plugins/table/types.js +12 -1
  30. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/ColumnDropTargets/index.js +101 -0
  31. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/index.js +60 -0
  32. package/dist/es2019/plugins/table/ui/common-styles.js +14 -1
  33. package/dist/es2019/plugins/table/ui/consts.js +1 -0
  34. package/dist/es2019/plugins/table/ui/ui-styles.js +127 -1
  35. package/dist/es2019/plugins/table/utils/decoration.js +62 -0
  36. package/dist/es2019/plugins/table/utils/index.js +3 -2
  37. package/dist/es2019/plugins/table/utils/merged-cells.js +48 -0
  38. package/dist/esm/plugins/table/nodeviews/TableComponent.js +20 -2
  39. package/dist/esm/plugins/table/nodeviews/table.js +1 -0
  40. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/commands.js +36 -7
  41. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/handlers.js +18 -0
  42. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/plugin-factory.js +28 -3
  43. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/plugin.js +82 -9
  44. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/reducer.js +2 -0
  45. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/utils/index.js +1 -0
  46. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/utils/monitor.js +53 -0
  47. package/dist/esm/plugins/table/types.js +12 -1
  48. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/ColumnDropTargets/index.js +97 -0
  49. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/index.js +80 -0
  50. package/dist/esm/plugins/table/ui/common-styles.js +2 -2
  51. package/dist/esm/plugins/table/ui/consts.js +1 -0
  52. package/dist/esm/plugins/table/ui/ui-styles.js +15 -9
  53. package/dist/esm/plugins/table/utils/decoration.js +66 -0
  54. package/dist/esm/plugins/table/utils/index.js +3 -2
  55. package/dist/esm/plugins/table/utils/merged-cells.js +60 -0
  56. package/dist/types/plugins/table/index.d.ts +1 -1
  57. package/dist/types/plugins/table/nodeviews/TableComponent.d.ts +1 -0
  58. package/dist/types/plugins/table/pm-plugins/drag-and-drop/actions.d.ts +5 -1
  59. package/dist/types/plugins/table/pm-plugins/drag-and-drop/commands.d.ts +6 -1
  60. package/dist/types/plugins/table/pm-plugins/drag-and-drop/handlers.d.ts +3 -0
  61. package/dist/types/plugins/table/pm-plugins/drag-and-drop/plugin-factory.d.ts +1 -2
  62. package/dist/types/plugins/table/pm-plugins/drag-and-drop/types.d.ts +2 -0
  63. package/dist/types/plugins/table/pm-plugins/drag-and-drop/utils/index.d.ts +1 -0
  64. package/dist/types/plugins/table/pm-plugins/drag-and-drop/utils/monitor.d.ts +3 -0
  65. package/dist/types/plugins/table/types.d.ts +23 -1
  66. package/dist/types/plugins/table/ui/TableFloatingColumnControls/ColumnDropTargets/index.d.ts +11 -0
  67. package/dist/types/plugins/table/ui/TableFloatingColumnControls/index.d.ts +20 -0
  68. package/dist/types/plugins/table/ui/consts.d.ts +1 -0
  69. package/dist/types/plugins/table/ui/ui-styles.d.ts +2 -0
  70. package/dist/types/plugins/table/utils/decoration.d.ts +2 -0
  71. package/dist/types/plugins/table/utils/index.d.ts +2 -1
  72. package/dist/types/plugins/table/utils/merged-cells.d.ts +3 -0
  73. package/dist/types-ts4.5/plugins/table/index.d.ts +1 -1
  74. package/dist/types-ts4.5/plugins/table/nodeviews/TableComponent.d.ts +1 -0
  75. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/actions.d.ts +5 -1
  76. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/commands.d.ts +6 -1
  77. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/handlers.d.ts +3 -0
  78. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/plugin-factory.d.ts +1 -2
  79. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/types.d.ts +2 -0
  80. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/utils/index.d.ts +1 -0
  81. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/utils/monitor.d.ts +3 -0
  82. package/dist/types-ts4.5/plugins/table/types.d.ts +23 -1
  83. package/dist/types-ts4.5/plugins/table/ui/TableFloatingColumnControls/ColumnDropTargets/index.d.ts +11 -0
  84. package/dist/types-ts4.5/plugins/table/ui/TableFloatingColumnControls/index.d.ts +20 -0
  85. package/dist/types-ts4.5/plugins/table/ui/consts.d.ts +1 -0
  86. package/dist/types-ts4.5/plugins/table/ui/ui-styles.d.ts +2 -0
  87. package/dist/types-ts4.5/plugins/table/utils/decoration.d.ts +2 -0
  88. package/dist/types-ts4.5/plugins/table/utils/index.d.ts +2 -1
  89. package/dist/types-ts4.5/plugins/table/utils/merged-cells.d.ts +3 -0
  90. package/package.json +4 -1
  91. package/src/__tests__/unit/ui/TableFloatingColumnControls.tsx +139 -0
  92. package/src/plugins/table/index.tsx +1 -1
  93. package/src/plugins/table/nodeviews/TableComponent.tsx +25 -0
  94. package/src/plugins/table/nodeviews/table.tsx +1 -0
  95. package/src/plugins/table/pm-plugins/drag-and-drop/actions.ts +6 -1
  96. package/src/plugins/table/pm-plugins/drag-and-drop/commands.ts +58 -8
  97. package/src/plugins/table/pm-plugins/drag-and-drop/handlers.ts +35 -0
  98. package/src/plugins/table/pm-plugins/drag-and-drop/plugin-factory.ts +27 -2
  99. package/src/plugins/table/pm-plugins/drag-and-drop/plugin.ts +88 -6
  100. package/src/plugins/table/pm-plugins/drag-and-drop/reducer.ts +2 -0
  101. package/src/plugins/table/pm-plugins/drag-and-drop/types.ts +3 -0
  102. package/src/plugins/table/pm-plugins/drag-and-drop/utils/index.ts +1 -0
  103. package/src/plugins/table/pm-plugins/drag-and-drop/utils/monitor.ts +72 -0
  104. package/src/plugins/table/types.ts +28 -1
  105. package/src/plugins/table/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +128 -0
  106. package/src/plugins/table/ui/TableFloatingColumnControls/index.tsx +101 -0
  107. package/src/plugins/table/ui/common-styles.ts +15 -0
  108. package/src/plugins/table/ui/consts.ts +1 -0
  109. package/src/plugins/table/ui/ui-styles.ts +129 -0
  110. package/src/plugins/table/utils/decoration.ts +101 -0
  111. package/src/plugins/table/utils/index.ts +3 -0
  112. package/src/plugins/table/utils/merged-cells.ts +67 -0
@@ -404,4 +404,66 @@ export const createColumnLineResize = (selection, cellColumnPositioning) => {
404
404
  key: `${TableDecorations.COLUMN_RESIZING_HANDLE_LINE}_${cellColumnPositioning.right}_${index}`
405
405
  });
406
406
  }).filter(nonNullable);
407
+ };
408
+ export const createColumnInsertLine = (columnIndex, selection) => {
409
+ const table = findTable(selection);
410
+ if (!table) {
411
+ return [];
412
+ }
413
+ const map = TableMap.get(table.node);
414
+ const isFirstColumn = columnIndex === 0;
415
+ const isLastColumn = columnIndex === map.width;
416
+ if (isLastColumn) {
417
+ columnIndex -= 1;
418
+ }
419
+ const decorationClassName = isFirstColumn ? ClassName.WITH_FIRST_COLUMN_INSERT_LINE : isLastColumn ? ClassName.WITH_LAST_COLUMN_INSERT_LINE : ClassName.WITH_COLUMN_INSERT_LINE;
420
+ const cellPositions = makeArray(map.height).map(rowIndex => map.map[map.width * rowIndex + columnIndex]).filter((cellPosition, rowIndex) => {
421
+ if (isLastColumn) {
422
+ return true; // If is the last column no filter applied
423
+ }
424
+
425
+ const nextPosition = map.map[map.width * rowIndex + columnIndex - 1];
426
+ return cellPosition !== nextPosition; // Removed it if next position is merged
427
+ });
428
+
429
+ const cells = cellPositions.map(pos => ({
430
+ pos: pos + table.start,
431
+ node: table.node.nodeAt(pos)
432
+ }));
433
+ return cells.map((cell, index) => {
434
+ if (!cell || !cell.node) {
435
+ return;
436
+ }
437
+ return Decoration.node(cell.pos, cell.pos + cell.node.nodeSize, {
438
+ class: decorationClassName
439
+ }, {
440
+ key: `${TableDecorations.COLUMN_INSERT_LINE}_${index}`
441
+ });
442
+ }).filter(nonNullable);
443
+ };
444
+ export const createRowInsertLine = (rowIndex, selection) => {
445
+ const table = findTable(selection);
446
+ if (!table) {
447
+ return [];
448
+ }
449
+ const map = TableMap.get(table.node);
450
+ const isLastRow = rowIndex === map.height;
451
+ if (isLastRow) {
452
+ rowIndex -= 1;
453
+ }
454
+ const cells = getCellsInRow(rowIndex)(selection);
455
+ if (!cells) {
456
+ return [];
457
+ }
458
+ const decorationClassName = isLastRow ? ClassName.WITH_LAST_ROW_INSERT_LINE : ClassName.WITH_ROW_INSERT_LINE;
459
+ return cells.map((cell, index) => {
460
+ if (!cell || !cell.node) {
461
+ return;
462
+ }
463
+ return Decoration.node(cell.pos, cell.pos + cell.node.nodeSize, {
464
+ class: decorationClassName
465
+ }, {
466
+ key: `${TableDecorations.ROW_INSERT_LINE}_${index}`
467
+ });
468
+ }).filter(nonNullable);
407
469
  };
@@ -1,5 +1,5 @@
1
1
  export { getSelectedColumnIndexes, getSelectedRowIndexes, normalizeSelection, isSelectionUpdated } from './selection';
2
- export { findControlsHoverDecoration, createControlsHoverDecoration, createColumnControlsDecoration, createColumnSelectedDecoration, createCellHoverDecoration, updateDecorations, createResizeHandleDecoration, createColumnLineResize } from './decoration';
2
+ export { findControlsHoverDecoration, createControlsHoverDecoration, createColumnControlsDecoration, createColumnSelectedDecoration, createCellHoverDecoration, updateDecorations, createResizeHandleDecoration, createColumnInsertLine, createColumnLineResize, createRowInsertLine } from './decoration';
3
3
  export { isIsolating, containsHeaderColumn, containsHeaderRow, checkIfHeaderColumnEnabled, checkIfHeaderRowEnabled, checkIfNumberColumnEnabled, isLayoutSupported, getTableWidth, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns, isTableNested, anyChildCellMergedAcrossRow, supportedHeaderRow } from './nodes';
4
4
  export { unwrapContentFromTable, removeTableFromFirstChild, removeTableFromLastChild, transformSliceToRemoveOpenTable, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell } from './paste';
5
5
  export { isCell, isCornerButton, isInsertRowButton, isColumnControlsDecorations, isTableControlsButton, isTableContainerOrWrapper, isRowControlsButton, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, updateResizeHandles, isResizeHandleDecoration, hasResizeHandler } from './dom';
@@ -7,4 +7,5 @@ export { getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonPar
7
7
  export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getRowsParams, getRowClassNames, copyPreviousRow } from './row-controls';
8
8
  export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
9
9
  export { getMergedCellsPositions } from './table';
10
- export { updatePluginStateDecorations } from './update-plugin-state-decorations';
10
+ export { updatePluginStateDecorations } from './update-plugin-state-decorations';
11
+ export { hasMergedCellsInColumn, hasMergedCellsInRow } from './merged-cells';
@@ -0,0 +1,48 @@
1
+ import { findTable, TableMap } from '@atlaskit/editor-tables';
2
+ const hasMergedCells = (indexes, normalizeRect) => selection => {
3
+ const table = findTable(selection);
4
+ if (!table) {
5
+ return false;
6
+ }
7
+ const map = TableMap.get(table.node);
8
+ const cellPositions = new Set();
9
+ const mergedCells = new Set();
10
+ map.map.forEach(value => {
11
+ if (cellPositions.has(value)) {
12
+ mergedCells.add(value);
13
+ } else {
14
+ cellPositions.add(value);
15
+ }
16
+ });
17
+ if (!mergedCells.size) {
18
+ return false;
19
+ }
20
+ return (Array.isArray(indexes) ? indexes : [indexes]).map(index => normalizeRect(index, map)).filter(rect => rect.left < rect.right && rect.top < rect.bottom).some(rect => {
21
+ const n = (rect.right - rect.left) * (rect.bottom - rect.top);
22
+ const cells = map.cellsInRect(rect);
23
+ if (cells.length !== n) {
24
+ // We can quickly assume that if the amount of cells from the map is different to what the rect says
25
+ // then there is most likely merged cells across this area which is removing cells
26
+ return true;
27
+ }
28
+ return cells.some(nodePos => mergedCells.has(nodePos));
29
+ });
30
+ };
31
+ export const hasMergedCellsInColumn = columnIndexes => hasMergedCells(columnIndexes, (index, map) => {
32
+ const x = Math.max(Math.min(index, map.width - 1), 0); // clamped index
33
+ return {
34
+ left: x,
35
+ right: x === index ? x + 1 : x,
36
+ top: 0,
37
+ bottom: map.height
38
+ };
39
+ });
40
+ export const hasMergedCellsInRow = rowIndexes => hasMergedCells(rowIndexes, (index, map) => {
41
+ const y = Math.max(Math.min(index, map.height - 1), 0); // clamped index
42
+ return {
43
+ left: 0,
44
+ right: map.width,
45
+ top: y,
46
+ bottom: y === index ? y + 1 : y
47
+ };
48
+ });
@@ -30,6 +30,7 @@ import { hasTableBeenResized } from '../pm-plugins/table-resizing/utils/colgroup
30
30
  import { updateControls } from '../pm-plugins/table-resizing/utils/dom';
31
31
  import { TableCssClassName as ClassName, ShadowEvent } from '../types';
32
32
  import { tableOverflowShadowWidth, tableOverflowShadowWidthWide } from '../ui/consts';
33
+ import TableFloatingColumnControls from '../ui/TableFloatingColumnControls';
33
34
  import TableFloatingControls from '../ui/TableFloatingControls';
34
35
  import { containsHeaderRow, isTableNested, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns } from '../utils';
35
36
  import { OverflowShadowsObserver } from './OverflowShadowsObserver';
@@ -452,7 +453,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
452
453
  containerWidth = _this$props10.containerWidth,
453
454
  options = _this$props10.options,
454
455
  getPos = _this$props10.getPos,
455
- pluginInjectionApi = _this$props10.pluginInjectionApi;
456
+ pluginInjectionApi = _this$props10.pluginInjectionApi,
457
+ isDragAndDropEnabled = _this$props10.isDragAndDropEnabled;
456
458
  var _this$state3 = this.state,
457
459
  showBeforeShadow = _this$state3.showBeforeShadow,
458
460
  showAfterShadow = _this$state3.showAfterShadow;
@@ -485,6 +487,22 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
485
487
  stickyHeader: this.state.stickyHeader,
486
488
  getEditorFeatureFlags: this.props.getEditorFeatureFlags
487
489
  }));
490
+ var colControls = /*#__PURE__*/React.createElement("div", {
491
+ className: ClassName.COLUMN_CONTROLS_WRAPPER
492
+ }, /*#__PURE__*/React.createElement(TableFloatingColumnControls, {
493
+ editorView: view,
494
+ tableRef: tableRef,
495
+ tableActive: tableActive,
496
+ hoveredRows: hoveredRows,
497
+ ordering: ordering,
498
+ hasHeaderRow: hasHeaderRow
499
+ // pass `selection` and `tableHeight` to control re-render
500
+ ,
501
+ selection: view.state.selection,
502
+ headerRowHeight: headerRow ? headerRow.offsetHeight : undefined,
503
+ stickyHeader: this.state.stickyHeader,
504
+ getEditorFeatureFlags: this.props.getEditorFeatureFlags
505
+ }));
488
506
  var shadowPadding = allowControls && tableActive ? -tableToolbarSize : tableMarginSides;
489
507
  var shadowStyle = memoizeOne(function (visible) {
490
508
  return {
@@ -522,7 +540,7 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
522
540
  }), getBooleanFF('platform.editor.table-sticky-scrollbar') && /*#__PURE__*/React.createElement("div", {
523
541
  className: ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP,
524
542
  "data-testid": "sticky-scrollbar-sentinel-top"
525
- }), allowControls && rowControls, /*#__PURE__*/React.createElement("div", {
543
+ }), allowControls && rowControls, isDragAndDropEnabled && allowControls && colControls, /*#__PURE__*/React.createElement("div", {
526
544
  style: shadowStyle(showBeforeShadow),
527
545
  className: ClassName.TABLE_LEFT_SHADOW
528
546
  }), this.state.stickyHeader && /*#__PURE__*/React.createElement("div", {
@@ -169,6 +169,7 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
169
169
  allowControls: pluginState.pluginConfig.allowControls,
170
170
  isHeaderRowEnabled: pluginState.isHeaderRowEnabled,
171
171
  isHeaderColumnEnabled: pluginState.isHeaderColumnEnabled,
172
+ isDragAndDropEnabled: pluginState.isDragAndDropEnabled,
172
173
  tableActive: tableActive,
173
174
  ordering: pluginState.ordering,
174
175
  isResizing: isResizing,
@@ -1,21 +1,50 @@
1
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
2
+ import { TableDecorations } from '../../types';
3
+ import { createColumnInsertLine, createRowInsertLine, updateDecorations } from '../../utils';
1
4
  import { DragAndDropActionType } from './actions';
2
- import { createCommand } from './plugin-factory';
5
+ import { createCommand, getPluginState } from './plugin-factory';
6
+ import { pluginKey } from './plugin-key';
3
7
 
4
8
  // TODO: This command is a placeholder example. Please replace this if required.
9
+ export var getDecorations = function getDecorations(state) {
10
+ var _pluginKey$getState;
11
+ return ((_pluginKey$getState = pluginKey.getState(state)) === null || _pluginKey$getState === void 0 ? void 0 : _pluginKey$getState.decorationSet) || DecorationSet.empty;
12
+ };
13
+ export var updatePluginStateDecorations = function updatePluginStateDecorations(state, decorations, key) {
14
+ return updateDecorations(state.doc, getDecorations(state), decorations, key);
15
+ };
5
16
  export var setDropTarget = function setDropTarget(type, index, tr) {
6
- return createCommand({
7
- type: DragAndDropActionType.SET_DROP_TARGET,
8
- data: {
9
- type: type,
10
- index: index
17
+ return createCommand(function (state) {
18
+ var _getPluginState = getPluginState(state),
19
+ dropTargetType = _getPluginState.dropTargetType,
20
+ dropTargetIndex = _getPluginState.dropTargetIndex;
21
+ if (dropTargetType === type && dropTargetIndex === index) {
22
+ return false;
11
23
  }
24
+ var decorationSet = DecorationSet.empty;
25
+ if (type === 'column') {
26
+ decorationSet = updatePluginStateDecorations(state, createColumnInsertLine(index, state.selection), TableDecorations.COLUMN_INSERT_LINE);
27
+ } else if (type === 'row') {
28
+ decorationSet = updatePluginStateDecorations(state, createRowInsertLine(index, state.selection), TableDecorations.ROW_INSERT_LINE);
29
+ }
30
+ return {
31
+ type: DragAndDropActionType.SET_DROP_TARGET,
32
+ data: {
33
+ decorationSet: decorationSet,
34
+ type: type,
35
+ index: index
36
+ }
37
+ };
12
38
  }, function (originalTr) {
13
39
  return (tr || originalTr).setMeta('addToHistory', false);
14
40
  });
15
41
  };
16
42
  export var clearDropTarget = function clearDropTarget(tr) {
17
43
  return createCommand({
18
- type: DragAndDropActionType.CLEAR_DROP_TARGET
44
+ type: DragAndDropActionType.CLEAR_DROP_TARGET,
45
+ data: {
46
+ decorationSet: DecorationSet.empty
47
+ }
19
48
  }, function (originalTr) {
20
49
  return (tr || originalTr).setMeta('addToHistory', false);
21
50
  });
@@ -0,0 +1,18 @@
1
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
2
+
3
+ import { findTable } from '@atlaskit/editor-tables/utils';
4
+ var buildPluginState = function buildPluginState(builders) {
5
+ return function (props) {
6
+ return function (pluginState) {
7
+ return builders.reduce(function (_pluginState, transform) {
8
+ return transform(props)(_pluginState);
9
+ }, pluginState);
10
+ };
11
+ };
12
+ };
13
+ export var handleDocOrSelectionChanged = function handleDocOrSelectionChanged(tr, pluginState) {
14
+ return buildPluginState([])({
15
+ tr: tr,
16
+ table: findTable(tr.selection)
17
+ })(pluginState);
18
+ };
@@ -1,7 +1,32 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1
4
  import { pluginFactory } from '@atlaskit/editor-common/utils';
5
+ import { pluginKey as tablePluginKey } from '../plugin-key';
6
+ import { handleDocOrSelectionChanged } from './handlers';
2
7
  import { pluginKey } from './plugin-key';
3
8
  import reducer from './reducer';
4
- var _pluginFactory = pluginFactory(pluginKey, reducer),
9
+ var _pluginFactory = pluginFactory(pluginKey, reducer, {
10
+ mapping: function mapping(tr, pluginState) {
11
+ if (tr.docChanged) {
12
+ var decorationSet = pluginState.decorationSet;
13
+ var meta = tr.getMeta(tablePluginKey);
14
+ if (meta && meta.data && meta.data.decorationSet) {
15
+ decorationSet = meta.data.decorationSet;
16
+ }
17
+ if (decorationSet) {
18
+ decorationSet = decorationSet.map(tr.mapping, tr.doc);
19
+ }
20
+ return _objectSpread(_objectSpread({}, pluginState), {
21
+ decorationSet: decorationSet
22
+ });
23
+ }
24
+ return pluginState;
25
+ },
26
+ onDocChanged: handleDocOrSelectionChanged,
27
+ onSelectionChanged: handleDocOrSelectionChanged
28
+ }),
5
29
  createPluginState = _pluginFactory.createPluginState,
6
- createCommand = _pluginFactory.createCommand;
7
- export { createPluginState, createCommand };
30
+ createCommand = _pluginFactory.createCommand,
31
+ getPluginState = _pluginFactory.getPluginState;
32
+ export { createPluginState, createCommand, getPluginState };
@@ -1,22 +1,95 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
+ import { moveColumn, moveRow } from '@atlaskit/editor-tables/utils';
5
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
6
+ import { hasMergedCellsInColumn, hasMergedCellsInRow } from '../../utils/merged-cells';
7
+ import { getPluginState as getTablePluginState } from '../plugin-factory';
2
8
  import { DropTargetType } from './consts';
3
- import { createPluginState } from './plugin-factory';
9
+ import { createPluginState, getPluginState } from './plugin-factory';
4
10
  import { pluginKey } from './plugin-key';
11
+ import { getDraggableDataFromEvent } from './utils/monitor';
5
12
  export var createPlugin = function createPlugin(dispatch, eventDispatcher) {
6
13
  return new SafePlugin({
7
- state: createPluginState(dispatch, {
8
- // TODO: This is example placeholder state. We could use this to track which row/col is currently set as the drop target
9
- // This would result in a blue highlight being displayed on the corrisponding row/column to single the drop target location.
10
- dropTargetType: DropTargetType.NONE,
11
- dropTargetIndex: 0
14
+ state: createPluginState(dispatch, function (state) {
15
+ return {
16
+ decorationSet: DecorationSet.empty,
17
+ // TODO: This is example placeholder state. We could use this to track which row/col is currently set as the drop target
18
+ // This would result in a blue highlight being displayed on the corrisponding row/column to single the drop target location.
19
+ dropTargetType: DropTargetType.NONE,
20
+ dropTargetIndex: 0
21
+ };
12
22
  }),
13
23
  key: pluginKey,
14
24
  view: function view(editorView) {
15
- // TODO: Add Pragmatic DnD monitor when the view is constructed.
16
25
  return {
17
- // TODO: Cleanup monitor instance
18
- // destroy: cleanup,
26
+ destroy: monitorForElements({
27
+ canMonitor: function canMonitor(_ref) {
28
+ var source = _ref.source;
29
+ var _ref2 = source.data,
30
+ type = _ref2.type,
31
+ localId = _ref2.localId,
32
+ indexes = _ref2.indexes;
33
+
34
+ // First; Perform any quick checks so we can abort early.
35
+ if (!indexes || !localId ||
36
+ // FIXME: We currently don't support DragNDrop of multiple elements. For now we will not bother to monitor drags
37
+ // of more then 1 item.
38
+ indexes.length !== 1 || !(type === 'table-row' || type === 'table-column')) {
39
+ return false;
40
+ }
41
+ var _getTablePluginState = getTablePluginState(editorView.state),
42
+ tableNode = _getTablePluginState.tableNode;
43
+ // If the draggable localId is the same as the current selected table localId then we will allow the monitor
44
+ // watch for changes
45
+ return localId === (tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.localId);
46
+ },
47
+ onDrag: function onDrag(event) {
48
+ var data = getDraggableDataFromEvent(event);
49
+
50
+ // If no data can be found then it's most like we do not want to perform any drag actions
51
+ if (!data) {
52
+ return;
53
+ }
54
+
55
+ // TODO: as we drag an element around we are going to want to update the state to acurately reflect the current
56
+ // insert location as to where the draggable will most likely be go. For example;
57
+ // const { sourceType, targetAdjustedIndex } = data;
58
+ // const highlight = sourceType === 'table-row' ? highlightRow : highlightColumn;
59
+ // return editorView.dispatch(
60
+ // highlight(targetAdjustedIndex)(editorView.state.tr),
61
+ // );
62
+ },
63
+ onDrop: function onDrop(event) {
64
+ var data = getDraggableDataFromEvent(event);
65
+
66
+ // If no data can be found then it's most like we do not want to perform any drop action
67
+ if (!data) {
68
+ return;
69
+ }
70
+ var sourceType = data.sourceType,
71
+ sourceIndexes = data.sourceIndexes,
72
+ targetAdjustedIndex = data.targetAdjustedIndex;
73
+
74
+ // If the drop target index contains merged cells then we should not allow the drop to occur.
75
+ var hasMergedCells = sourceType === 'table-row' ? hasMergedCellsInRow : hasMergedCellsInColumn;
76
+ if (hasMergedCells(targetAdjustedIndex)(editorView.state.selection)) {
77
+ return;
78
+ }
79
+ var move = sourceType === 'table-row' ? moveRow : moveColumn;
80
+ var _sourceIndexes = _slicedToArray(sourceIndexes, 1),
81
+ sourceIndex = _sourceIndexes[0];
82
+ return editorView.dispatch(move(sourceIndex, targetAdjustedIndex)(editorView.state.tr));
83
+ }
84
+ })
19
85
  };
86
+ },
87
+ props: {
88
+ decorations: function decorations(state) {
89
+ var _getPluginState = getPluginState(state),
90
+ decorationSet = _getPluginState.decorationSet;
91
+ return decorationSet;
92
+ }
20
93
  }
21
94
  });
22
95
  };
@@ -7,11 +7,13 @@ export default (function (pluginState, action) {
7
7
  switch (action.type) {
8
8
  case DragAndDropActionType.SET_DROP_TARGET:
9
9
  return _objectSpread(_objectSpread({}, pluginState), {}, {
10
+ decorationSet: action.data.decorationSet,
10
11
  dropTargetType: action.data.type,
11
12
  dropTargetIndex: action.data.index
12
13
  });
13
14
  case DragAndDropActionType.CLEAR_DROP_TARGET:
14
15
  return _objectSpread(_objectSpread({}, pluginState), {}, {
16
+ decorationSet: action.data.decorationSet,
15
17
  dropTargetType: DropTargetType.NONE,
16
18
  dropTargetIndex: 0
17
19
  });
@@ -0,0 +1 @@
1
+ export { getDraggableDataFromEvent } from './monitor';
@@ -0,0 +1,53 @@
1
+ import { extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/addon/closest-edge';
2
+ export var getDraggableDataFromEvent = function getDraggableDataFromEvent(_ref) {
3
+ var _extractClosestEdge;
4
+ var location = _ref.location,
5
+ source = _ref.source;
6
+ var destination = location.current.dropTargets.at(0);
7
+ // If no target exists at the current location, then the current draggable is not over a target or the target doesn't support
8
+ // the current draggable.
9
+ if (!destination) {
10
+ return undefined;
11
+ }
12
+
13
+ // This is the draggable elements data
14
+ var _ref2 = source.data,
15
+ sourceIndexes = _ref2.indexes,
16
+ sourceType = _ref2.type,
17
+ sourceLocalId = _ref2.localId;
18
+
19
+ // This is the drop target's data
20
+ var _ref3 = destination.data,
21
+ targetIndex = _ref3.targetIndex,
22
+ targetType = _ref3.type,
23
+ targetLocalId = _ref3.localId;
24
+
25
+ // Some basic check to abort early with...
26
+ if (!sourceIndexes || targetIndex < 0 ||
27
+ // abort if the type of the draggable is different to the target, for eg. rows cannot be dropped onto column targets.
28
+ sourceType !== targetType ||
29
+ // abort if the draggable is coming from a different table that the target is on.
30
+ sourceLocalId !== targetLocalId) {
31
+ return undefined;
32
+ }
33
+
34
+ // FIXME: currently we only support a single row/col index being moved, remove this clause when this is no longer the case.
35
+ if (sourceIndexes.length > 1) {
36
+ return undefined;
37
+ }
38
+ var targetClosestEdge = (_extractClosestEdge = extractClosestEdge(destination.data)) !== null && _extractClosestEdge !== void 0 ? _extractClosestEdge : targetType === 'table-row' ? 'top' : 'left';
39
+ // NOTE: By default we always insert row/cols at the target index to the top/left (retrospectively of row/cols).
40
+ // This introduces an offset in the event the drop occured closer to the bottom/right of the target. We want
41
+ // the new target index to be 1 index higher.
42
+ var targetOffset = targetClosestEdge === 'right' || targetClosestEdge === 'bottom' ? 1 : 0;
43
+ return {
44
+ sourceType: sourceType,
45
+ sourceLocalId: sourceLocalId,
46
+ sourceIndexes: sourceIndexes,
47
+ targetType: targetType,
48
+ targetLocalId: targetLocalId,
49
+ targetIndex: targetIndex,
50
+ targetAdjustedIndex: targetIndex + targetOffset,
51
+ targetClosestEdge: targetClosestEdge
52
+ };
53
+ };
@@ -37,10 +37,13 @@ export var TableDecorations = /*#__PURE__*/function (TableDecorations) {
37
37
  TableDecorations["TABLE_CONTROLS_HOVER"] = "TABLE_CONTROLS_HOVER";
38
38
  TableDecorations["CELL_CONTROLS_HOVER"] = "CELL_CONTROLS_HOVER";
39
39
  TableDecorations["COLUMN_CONTROLS_DECORATIONS"] = "COLUMN_CONTROLS_DECORATIONS";
40
+ TableDecorations["COLUMN_DROP_TARGET_DECORATIONS"] = "COLUMN_DROP_TARGET_DECORATIONS";
40
41
  TableDecorations["COLUMN_SELECTED"] = "COLUMN_SELECTED";
41
42
  TableDecorations["COLUMN_RESIZING_HANDLE"] = "COLUMN_RESIZING_HANDLE";
42
43
  TableDecorations["COLUMN_RESIZING_HANDLE_WIDGET"] = "COLUMN_RESIZING_HANDLE_WIDGET";
43
44
  TableDecorations["COLUMN_RESIZING_HANDLE_LINE"] = "COLUMN_RESIZING_HANDLE_LINE";
45
+ TableDecorations["COLUMN_INSERT_LINE"] = "COLUMN_INSERT_LINE";
46
+ TableDecorations["ROW_INSERT_LINE"] = "ROW_INSERT_LINE";
44
47
  TableDecorations["LAST_CELL_ELEMENT"] = "LAST_CELL_ELEMENT";
45
48
  return TableDecorations;
46
49
  }({});
@@ -48,6 +51,9 @@ export var TableCssClassName = _objectSpread(_objectSpread({}, TableSharedCssCla
48
51
  COLUMN_CONTROLS: "".concat(tablePrefixSelector, "-column-controls"),
49
52
  COLUMN_CONTROLS_DECORATIONS: "".concat(tablePrefixSelector, "-column-controls-decoration"),
50
53
  COLUMN_SELECTED: "".concat(tablePrefixSelector, "-column__selected"),
54
+ COLUMN_CONTROLS_WRAPPER: "".concat(tablePrefixSelector, "-col-controls-wrapper"),
55
+ COLUMN_DROP_TARGET_CONTROLS: "".concat(tablePrefixSelector, "-col-drop-target-controls"),
56
+ COLUMN_CONTROLS_INNER: "".concat(tablePrefixSelector, "-col-controls__inner"),
51
57
  ROW_CONTROLS_WRAPPER: "".concat(tablePrefixSelector, "-row-controls-wrapper"),
52
58
  ROW_CONTROLS: "".concat(tablePrefixSelector, "-row-controls"),
53
59
  ROW_CONTROLS_INNER: "".concat(tablePrefixSelector, "-row-controls__inner"),
@@ -104,8 +110,13 @@ export var TableCssClassName = _objectSpread(_objectSpread({}, TableSharedCssCla
104
110
  TABLE_STICKY: "".concat(tablePrefixSelector, "-sticky"),
105
111
  TOP_LEFT_CELL: 'table > tbody > tr:nth-child(2) > td:nth-child(1)',
106
112
  LAST_ITEM_IN_CELL: "".concat(tablePrefixSelector, "-last-item-in-cell"),
113
+ WITH_COLUMN_INSERT_LINE: "".concat(tablePrefixSelector, "-column-insert-line"),
114
+ WITH_FIRST_COLUMN_INSERT_LINE: "".concat(tablePrefixSelector, "-first-column-insert-line"),
115
+ WITH_LAST_COLUMN_INSERT_LINE: "".concat(tablePrefixSelector, "-last-column-insert-line"),
107
116
  WITH_RESIZE_LINE: "".concat(tablePrefixSelector, "-column-resize-line"),
108
- WITH_RESIZE_LINE_LAST_COLUMN: "".concat(tablePrefixSelector, "-column-resize-line-last-column")
117
+ WITH_RESIZE_LINE_LAST_COLUMN: "".concat(tablePrefixSelector, "-column-resize-line-last-column"),
118
+ WITH_ROW_INSERT_LINE: "".concat(tablePrefixSelector, "-row-insert-line"),
119
+ WITH_LAST_ROW_INSERT_LINE: "".concat(tablePrefixSelector, "-last-row-insert-line")
109
120
  });
110
121
  export var ShadowEvent = /*#__PURE__*/function (ShadowEvent) {
111
122
  ShadowEvent["SHOW_BEFORE_SHADOW"] = "showBeforeShadow";
@@ -0,0 +1,97 @@
1
+ import React, { useEffect, useMemo, useRef } from 'react';
2
+ import { attachClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/addon/closest-edge';
3
+ import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
4
+ import { TableCssClassName as ClassName } from '../../../types';
5
+ import { getColumnsWidths, getRowHeights } from '../../../utils';
6
+ export var ColumnDropTargets = function ColumnDropTargets(_ref) {
7
+ var _rowHeights$;
8
+ var editorView = _ref.editorView,
9
+ tableRef = _ref.tableRef,
10
+ tableHeight = _ref.tableHeight,
11
+ stickyTop = _ref.stickyTop,
12
+ localId = _ref.localId;
13
+ var colWidths = getColumnsWidths(editorView);
14
+ var rowHeights = useMemo(function () {
15
+ // NOTE: we don't care so much as to what tableHeight is, we only care that it changed and is a sane value.
16
+ if (tableRef && !!tableHeight) {
17
+ return getRowHeights(tableRef);
18
+ }
19
+ return [0];
20
+ }, [tableRef, tableHeight]);
21
+ if (!tableRef) {
22
+ return null;
23
+ }
24
+ var firstRow = tableRef.querySelector('tr');
25
+ var hasHeaderRow = firstRow ? firstRow.getAttribute('data-header-row') : false;
26
+ var marginTop = hasHeaderRow && stickyTop !== undefined ? (_rowHeights$ = rowHeights === null || rowHeights === void 0 ? void 0 : rowHeights[0]) !== null && _rowHeights$ !== void 0 ? _rowHeights$ : 0 : 0;
27
+ return /*#__PURE__*/React.createElement("div", {
28
+ className: ClassName.COLUMN_DROP_TARGET_CONTROLS
29
+ }, /*#__PURE__*/React.createElement("div", {
30
+ className: ClassName.COLUMN_CONTROLS_INNER,
31
+ "data-testid": "table-floating-column-controls-drop-targets"
32
+ }, colWidths.map(function (width, index) {
33
+ return /*#__PURE__*/React.createElement(ColumnDropTarget, {
34
+ key: index,
35
+ index: index,
36
+ localId: localId,
37
+ width: width,
38
+ height: tableHeight,
39
+ marginTop: marginTop
40
+ });
41
+ })));
42
+ };
43
+ export default ColumnDropTargets;
44
+ var ColumnDropTarget = function ColumnDropTarget(_ref2) {
45
+ var index = _ref2.index,
46
+ localId = _ref2.localId,
47
+ width = _ref2.width,
48
+ height = _ref2.height,
49
+ marginTop = _ref2.marginTop;
50
+ var dropTargetRef = useRef(null);
51
+ useEffect(function () {
52
+ if (!dropTargetRef.current) {
53
+ return;
54
+ }
55
+ return dropTargetForElements({
56
+ element: dropTargetRef.current,
57
+ canDrop: function canDrop(_ref3) {
58
+ var _data$indexes, _data$indexes2;
59
+ var source = _ref3.source;
60
+ var data = source.data;
61
+ return (
62
+ // Only draggables of row type can be dropped on this target
63
+ data.type === 'table-column' &&
64
+ // Only draggables which came from the same table can be dropped on this target
65
+ data.localId === localId &&
66
+ // Only draggables which DO NOT include this drop targets index can be dropped
67
+ !!((_data$indexes = data.indexes) !== null && _data$indexes !== void 0 && _data$indexes.length) && ((_data$indexes2 = data.indexes) === null || _data$indexes2 === void 0 ? void 0 : _data$indexes2.indexOf(index)) === -1
68
+ );
69
+ },
70
+ getData: function getData(_ref4) {
71
+ var input = _ref4.input,
72
+ element = _ref4.element;
73
+ var data = {
74
+ localId: localId,
75
+ type: 'table-column',
76
+ targetIndex: index
77
+ };
78
+ return attachClosestEdge(data, {
79
+ input: input,
80
+ element: element,
81
+ allowedEdges: ['left', 'right']
82
+ });
83
+ }
84
+ });
85
+ }, [index, localId]);
86
+ return /*#__PURE__*/React.createElement("div", {
87
+ ref: dropTargetRef,
88
+ style: {
89
+ width: width && "".concat(width - 1, "px"),
90
+ height: height && "".concat(height, "px"),
91
+ marginTop: marginTop && "".concat(marginTop, "px")
92
+ },
93
+ "data-drop-target-index": index,
94
+ "data-drop-target-localid": localId,
95
+ "data-testid": "table-floating-column-controls-drop-target"
96
+ });
97
+ };