@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
@@ -1,8 +1,32 @@
1
1
  import { pluginFactory } from '@atlaskit/editor-common/utils';
2
+ import { pluginKey as tablePluginKey } from '../plugin-key';
3
+ import { handleDocOrSelectionChanged } from './handlers';
2
4
  import { pluginKey } from './plugin-key';
3
5
  import reducer from './reducer';
4
- const {
6
+ export const {
5
7
  createPluginState,
6
- createCommand
7
- } = pluginFactory(pluginKey, reducer);
8
- export { createPluginState, createCommand };
8
+ createCommand,
9
+ getPluginState
10
+ } = pluginFactory(pluginKey, reducer, {
11
+ mapping: (tr, pluginState) => {
12
+ if (tr.docChanged) {
13
+ let decorationSet = pluginState.decorationSet;
14
+ const meta = tr.getMeta(tablePluginKey);
15
+ if (meta && meta.data && meta.data.decorationSet) {
16
+ decorationSet = meta.data.decorationSet;
17
+ }
18
+ if (decorationSet) {
19
+ decorationSet = decorationSet.map(tr.mapping, tr.doc);
20
+ }
21
+ return {
22
+ ...pluginState,
23
+ ...{
24
+ decorationSet
25
+ }
26
+ };
27
+ }
28
+ return pluginState;
29
+ },
30
+ onDocChanged: handleDocOrSelectionChanged,
31
+ onSelectionChanged: handleDocOrSelectionChanged
32
+ });
@@ -1,22 +1,98 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
+ import { moveColumn, moveRow } from '@atlaskit/editor-tables/utils';
4
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
5
+ import { hasMergedCellsInColumn, hasMergedCellsInRow } from '../../utils/merged-cells';
6
+ import { getPluginState as getTablePluginState } from '../plugin-factory';
2
7
  import { DropTargetType } from './consts';
3
- import { createPluginState } from './plugin-factory';
8
+ import { createPluginState, getPluginState } from './plugin-factory';
4
9
  import { pluginKey } from './plugin-key';
10
+ import { getDraggableDataFromEvent } from './utils/monitor';
5
11
  export const createPlugin = (dispatch, eventDispatcher) => {
6
12
  return new SafePlugin({
7
- state: createPluginState(dispatch, {
13
+ state: createPluginState(dispatch, state => ({
14
+ decorationSet: DecorationSet.empty,
8
15
  // TODO: This is example placeholder state. We could use this to track which row/col is currently set as the drop target
9
16
  // This would result in a blue highlight being displayed on the corrisponding row/column to single the drop target location.
10
17
  dropTargetType: DropTargetType.NONE,
11
18
  dropTargetIndex: 0
12
- }),
19
+ })),
13
20
  key: pluginKey,
14
21
  view: editorView => {
15
- // TODO: Add Pragmatic DnD monitor when the view is constructed.
16
22
  return {
17
- // TODO: Cleanup monitor instance
18
- // destroy: cleanup,
23
+ destroy: monitorForElements({
24
+ canMonitor({
25
+ source
26
+ }) {
27
+ const {
28
+ type,
29
+ localId,
30
+ indexes
31
+ } = source.data;
32
+
33
+ // First; Perform any quick checks so we can abort early.
34
+ if (!indexes || !localId ||
35
+ // FIXME: We currently don't support DragNDrop of multiple elements. For now we will not bother to monitor drags
36
+ // of more then 1 item.
37
+ indexes.length !== 1 || !(type === 'table-row' || type === 'table-column')) {
38
+ return false;
39
+ }
40
+ const {
41
+ tableNode
42
+ } = getTablePluginState(editorView.state);
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(event) {
48
+ const 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
+
64
+ onDrop(event) {
65
+ const data = getDraggableDataFromEvent(event);
66
+
67
+ // If no data can be found then it's most like we do not want to perform any drop action
68
+ if (!data) {
69
+ return;
70
+ }
71
+ const {
72
+ sourceType,
73
+ sourceIndexes,
74
+ targetAdjustedIndex
75
+ } = data;
76
+
77
+ // If the drop target index contains merged cells then we should not allow the drop to occur.
78
+ const hasMergedCells = sourceType === 'table-row' ? hasMergedCellsInRow : hasMergedCellsInColumn;
79
+ if (hasMergedCells(targetAdjustedIndex)(editorView.state.selection)) {
80
+ return;
81
+ }
82
+ const move = sourceType === 'table-row' ? moveRow : moveColumn;
83
+ const [sourceIndex] = sourceIndexes;
84
+ return editorView.dispatch(move(sourceIndex, targetAdjustedIndex)(editorView.state.tr));
85
+ }
86
+ })
19
87
  };
88
+ },
89
+ props: {
90
+ decorations: state => {
91
+ const {
92
+ decorationSet
93
+ } = getPluginState(state);
94
+ return decorationSet;
95
+ }
20
96
  }
21
97
  });
22
98
  };
@@ -5,12 +5,14 @@ export default ((pluginState, action) => {
5
5
  case DragAndDropActionType.SET_DROP_TARGET:
6
6
  return {
7
7
  ...pluginState,
8
+ decorationSet: action.data.decorationSet,
8
9
  dropTargetType: action.data.type,
9
10
  dropTargetIndex: action.data.index
10
11
  };
11
12
  case DragAndDropActionType.CLEAR_DROP_TARGET:
12
13
  return {
13
14
  ...pluginState,
15
+ decorationSet: action.data.decorationSet,
14
16
  dropTargetType: DropTargetType.NONE,
15
17
  dropTargetIndex: 0
16
18
  };
@@ -0,0 +1 @@
1
+ export { getDraggableDataFromEvent } from './monitor';
@@ -0,0 +1,56 @@
1
+ import { extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/addon/closest-edge';
2
+ export const getDraggableDataFromEvent = ({
3
+ location,
4
+ source
5
+ }) => {
6
+ var _extractClosestEdge;
7
+ const destination = location.current.dropTargets.at(0);
8
+ // If no target exists at the current location, then the current draggable is not over a target or the target doesn't support
9
+ // the current draggable.
10
+ if (!destination) {
11
+ return undefined;
12
+ }
13
+
14
+ // This is the draggable elements data
15
+ const {
16
+ indexes: sourceIndexes,
17
+ type: sourceType,
18
+ localId: sourceLocalId
19
+ } = source.data;
20
+
21
+ // This is the drop target's data
22
+ const {
23
+ targetIndex,
24
+ type: targetType,
25
+ localId: targetLocalId
26
+ } = destination.data;
27
+
28
+ // Some basic check to abort early with...
29
+ if (!sourceIndexes || targetIndex < 0 ||
30
+ // abort if the type of the draggable is different to the target, for eg. rows cannot be dropped onto column targets.
31
+ sourceType !== targetType ||
32
+ // abort if the draggable is coming from a different table that the target is on.
33
+ sourceLocalId !== targetLocalId) {
34
+ return undefined;
35
+ }
36
+
37
+ // FIXME: currently we only support a single row/col index being moved, remove this clause when this is no longer the case.
38
+ if (sourceIndexes.length > 1) {
39
+ return undefined;
40
+ }
41
+ const targetClosestEdge = (_extractClosestEdge = extractClosestEdge(destination.data)) !== null && _extractClosestEdge !== void 0 ? _extractClosestEdge : targetType === 'table-row' ? 'top' : 'left';
42
+ // NOTE: By default we always insert row/cols at the target index to the top/left (retrospectively of row/cols).
43
+ // This introduces an offset in the event the drop occured closer to the bottom/right of the target. We want
44
+ // the new target index to be 1 index higher.
45
+ const targetOffset = targetClosestEdge === 'right' || targetClosestEdge === 'bottom' ? 1 : 0;
46
+ return {
47
+ sourceType,
48
+ sourceLocalId,
49
+ sourceIndexes,
50
+ targetType,
51
+ targetLocalId,
52
+ targetIndex,
53
+ targetAdjustedIndex: targetIndex + targetOffset,
54
+ targetClosestEdge
55
+ };
56
+ };
@@ -34,10 +34,13 @@ export let TableDecorations = /*#__PURE__*/function (TableDecorations) {
34
34
  TableDecorations["TABLE_CONTROLS_HOVER"] = "TABLE_CONTROLS_HOVER";
35
35
  TableDecorations["CELL_CONTROLS_HOVER"] = "CELL_CONTROLS_HOVER";
36
36
  TableDecorations["COLUMN_CONTROLS_DECORATIONS"] = "COLUMN_CONTROLS_DECORATIONS";
37
+ TableDecorations["COLUMN_DROP_TARGET_DECORATIONS"] = "COLUMN_DROP_TARGET_DECORATIONS";
37
38
  TableDecorations["COLUMN_SELECTED"] = "COLUMN_SELECTED";
38
39
  TableDecorations["COLUMN_RESIZING_HANDLE"] = "COLUMN_RESIZING_HANDLE";
39
40
  TableDecorations["COLUMN_RESIZING_HANDLE_WIDGET"] = "COLUMN_RESIZING_HANDLE_WIDGET";
40
41
  TableDecorations["COLUMN_RESIZING_HANDLE_LINE"] = "COLUMN_RESIZING_HANDLE_LINE";
42
+ TableDecorations["COLUMN_INSERT_LINE"] = "COLUMN_INSERT_LINE";
43
+ TableDecorations["ROW_INSERT_LINE"] = "ROW_INSERT_LINE";
41
44
  TableDecorations["LAST_CELL_ELEMENT"] = "LAST_CELL_ELEMENT";
42
45
  return TableDecorations;
43
46
  }({});
@@ -46,6 +49,9 @@ export const TableCssClassName = {
46
49
  COLUMN_CONTROLS: `${tablePrefixSelector}-column-controls`,
47
50
  COLUMN_CONTROLS_DECORATIONS: `${tablePrefixSelector}-column-controls-decoration`,
48
51
  COLUMN_SELECTED: `${tablePrefixSelector}-column__selected`,
52
+ COLUMN_CONTROLS_WRAPPER: `${tablePrefixSelector}-col-controls-wrapper`,
53
+ COLUMN_DROP_TARGET_CONTROLS: `${tablePrefixSelector}-col-drop-target-controls`,
54
+ COLUMN_CONTROLS_INNER: `${tablePrefixSelector}-col-controls__inner`,
49
55
  ROW_CONTROLS_WRAPPER: `${tablePrefixSelector}-row-controls-wrapper`,
50
56
  ROW_CONTROLS: `${tablePrefixSelector}-row-controls`,
51
57
  ROW_CONTROLS_INNER: `${tablePrefixSelector}-row-controls__inner`,
@@ -102,8 +108,13 @@ export const TableCssClassName = {
102
108
  TABLE_STICKY: `${tablePrefixSelector}-sticky`,
103
109
  TOP_LEFT_CELL: 'table > tbody > tr:nth-child(2) > td:nth-child(1)',
104
110
  LAST_ITEM_IN_CELL: `${tablePrefixSelector}-last-item-in-cell`,
111
+ WITH_COLUMN_INSERT_LINE: `${tablePrefixSelector}-column-insert-line`,
112
+ WITH_FIRST_COLUMN_INSERT_LINE: `${tablePrefixSelector}-first-column-insert-line`,
113
+ WITH_LAST_COLUMN_INSERT_LINE: `${tablePrefixSelector}-last-column-insert-line`,
105
114
  WITH_RESIZE_LINE: `${tablePrefixSelector}-column-resize-line`,
106
- WITH_RESIZE_LINE_LAST_COLUMN: `${tablePrefixSelector}-column-resize-line-last-column`
115
+ WITH_RESIZE_LINE_LAST_COLUMN: `${tablePrefixSelector}-column-resize-line-last-column`,
116
+ WITH_ROW_INSERT_LINE: `${tablePrefixSelector}-row-insert-line`,
117
+ WITH_LAST_ROW_INSERT_LINE: `${tablePrefixSelector}-last-row-insert-line`
107
118
  };
108
119
  export let ShadowEvent = /*#__PURE__*/function (ShadowEvent) {
109
120
  ShadowEvent["SHOW_BEFORE_SHADOW"] = "showBeforeShadow";
@@ -0,0 +1,101 @@
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 const ColumnDropTargets = ({
7
+ editorView,
8
+ tableRef,
9
+ tableHeight,
10
+ stickyTop,
11
+ localId
12
+ }) => {
13
+ var _rowHeights$;
14
+ const colWidths = getColumnsWidths(editorView);
15
+ const rowHeights = useMemo(() => {
16
+ // NOTE: we don't care so much as to what tableHeight is, we only care that it changed and is a sane value.
17
+ if (tableRef && !!tableHeight) {
18
+ return getRowHeights(tableRef);
19
+ }
20
+ return [0];
21
+ }, [tableRef, tableHeight]);
22
+ if (!tableRef) {
23
+ return null;
24
+ }
25
+ const firstRow = tableRef.querySelector('tr');
26
+ const hasHeaderRow = firstRow ? firstRow.getAttribute('data-header-row') : false;
27
+ const marginTop = hasHeaderRow && stickyTop !== undefined ? (_rowHeights$ = rowHeights === null || rowHeights === void 0 ? void 0 : rowHeights[0]) !== null && _rowHeights$ !== void 0 ? _rowHeights$ : 0 : 0;
28
+ return /*#__PURE__*/React.createElement("div", {
29
+ className: ClassName.COLUMN_DROP_TARGET_CONTROLS
30
+ }, /*#__PURE__*/React.createElement("div", {
31
+ className: ClassName.COLUMN_CONTROLS_INNER,
32
+ "data-testid": "table-floating-column-controls-drop-targets"
33
+ }, colWidths.map((width, index) => {
34
+ return /*#__PURE__*/React.createElement(ColumnDropTarget, {
35
+ key: index,
36
+ index: index,
37
+ localId: localId,
38
+ width: width,
39
+ height: tableHeight,
40
+ marginTop: marginTop
41
+ });
42
+ })));
43
+ };
44
+ export default ColumnDropTargets;
45
+ const ColumnDropTarget = ({
46
+ index,
47
+ localId,
48
+ width,
49
+ height,
50
+ marginTop
51
+ }) => {
52
+ const dropTargetRef = useRef(null);
53
+ useEffect(() => {
54
+ if (!dropTargetRef.current) {
55
+ return;
56
+ }
57
+ return dropTargetForElements({
58
+ element: dropTargetRef.current,
59
+ canDrop({
60
+ source
61
+ }) {
62
+ var _data$indexes, _data$indexes2;
63
+ const data = source.data;
64
+ return (
65
+ // Only draggables of row type can be dropped on this target
66
+ data.type === 'table-column' &&
67
+ // Only draggables which came from the same table can be dropped on this target
68
+ data.localId === localId &&
69
+ // Only draggables which DO NOT include this drop targets index can be dropped
70
+ !!((_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
71
+ );
72
+ },
73
+ getData({
74
+ input,
75
+ element
76
+ }) {
77
+ const data = {
78
+ localId,
79
+ type: 'table-column',
80
+ targetIndex: index
81
+ };
82
+ return attachClosestEdge(data, {
83
+ input,
84
+ element,
85
+ allowedEdges: ['left', 'right']
86
+ });
87
+ }
88
+ });
89
+ }, [index, localId]);
90
+ return /*#__PURE__*/React.createElement("div", {
91
+ ref: dropTargetRef,
92
+ style: {
93
+ width: width && `${width - 1}px`,
94
+ height: height && `${height}px`,
95
+ marginTop: marginTop && `${marginTop}px`
96
+ },
97
+ "data-drop-target-index": index,
98
+ "data-drop-target-localid": localId,
99
+ "data-testid": "table-floating-column-controls-drop-target"
100
+ });
101
+ };
@@ -0,0 +1,60 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import { findTable } from '@atlaskit/editor-tables';
3
+ import { ColumnDropTargets } from './ColumnDropTargets';
4
+ export const TableFloatingColumnControls = ({
5
+ editorView,
6
+ tableRef,
7
+ tableActive,
8
+ hasHeaderRow,
9
+ stickyHeader,
10
+ selection
11
+ }) => {
12
+ const [tableRect, setTableRect] = useState({
13
+ width: 0,
14
+ height: 0
15
+ });
16
+ useEffect(() => {
17
+ var _window;
18
+ if (tableRef && (_window = window) !== null && _window !== void 0 && _window.ResizeObserver) {
19
+ const resizeObserver = new ResizeObserver(entries => {
20
+ for (let entry of entries) {
21
+ setTableRect(prev => {
22
+ if (prev.width !== entry.contentRect.width || prev.height !== entry.contentRect.height) {
23
+ return entry.contentRect;
24
+ }
25
+ return prev;
26
+ });
27
+ }
28
+ });
29
+ resizeObserver.observe(tableRef);
30
+ return () => {
31
+ resizeObserver.disconnect();
32
+ };
33
+ }
34
+ }, [tableRef]);
35
+ const selectedLocalId = useMemo(() => {
36
+ if (!selection) {
37
+ return undefined;
38
+ }
39
+ const tableNode = findTable(selection);
40
+ if (!tableNode) {
41
+ return undefined;
42
+ }
43
+ return tableNode.node.attrs.localId;
44
+ }, [selection]);
45
+ if (!tableRef) {
46
+ return null;
47
+ }
48
+ const stickyTop = stickyHeader && stickyHeader.sticky && hasHeaderRow ? stickyHeader.top : undefined;
49
+ return /*#__PURE__*/React.createElement("div", {
50
+ onMouseDown: e => e.preventDefault(),
51
+ "data-testid": "table-floating-column-controls-wrapper"
52
+ }, tableActive && /*#__PURE__*/React.createElement(ColumnDropTargets, {
53
+ editorView: editorView,
54
+ tableRef: tableRef,
55
+ stickyTop: tableActive ? stickyTop : undefined,
56
+ tableHeight: tableRect.height,
57
+ localId: selectedLocalId
58
+ }));
59
+ };
60
+ export default TableFloatingColumnControls;
@@ -7,7 +7,7 @@ import { B300, N0, N20A, N300, N40A, R500 } from '@atlaskit/theme/colors';
7
7
  import { fontSize } from '@atlaskit/theme/constants';
8
8
  import { TableCssClassName as ClassName } from '../types';
9
9
  import { columnControlsDecorationHeight, resizeHandlerAreaWidth, resizeLineWidth, stickyHeaderBorderBottomWidth, stickyRowOffsetTop, tableBorderColor, tableBorderDeleteColor, tableBorderRadiusSize, tableBorderSelectedColor, tableCellBackgroundColor, tableCellDeleteColor, tableCellSelectedColor, tableControlsSpacing, tableHeaderCellBackgroundColor, tableInsertColumnButtonSize, tableOverflowShadowWidth, tablePadding, tableScrollbarOffset, tableTextColor, tableToolbarDeleteColor, tableToolbarSelectedColor, tableToolbarSize } from './consts';
10
- import { columnControlsDecoration, columnControlsLineMarker, DeleteButton, HeaderButton, HeaderButtonDanger, HeaderButtonHover, hoveredCell, hoveredDeleteButton, hoveredWarningCell, insertColumnButtonWrapper, InsertMarker, insertRowButtonWrapper, OverflowShadow, resizeHandle } from './ui-styles';
10
+ import { columnControlsDecoration, columnControlsLineMarker, DeleteButton, floatingColumnControls, HeaderButton, HeaderButtonDanger, HeaderButtonHover, hoveredCell, hoveredDeleteButton, hoveredWarningCell, insertColumnButtonWrapper, insertLine, InsertMarker, insertRowButtonWrapper, OverflowShadow, resizeHandle } from './ui-styles';
11
11
  const cornerControlHeight = tableToolbarSize + 1;
12
12
 
13
13
  /*
@@ -210,6 +210,7 @@ export const tableStyles = props => {
210
210
  ${hoveredDeleteButton(props)};
211
211
  ${hoveredCell(props)};
212
212
  ${hoveredWarningCell};
213
+ ${getBooleanFF('platform.editor.table.drag-and-drop') && insertLine(props)};
213
214
  ${resizeHandle(props)};
214
215
  ${rangeSelectionStyles};
215
216
 
@@ -435,6 +436,10 @@ export const tableStyles = props => {
435
436
  }
436
437
  }
437
438
 
439
+ .${ClassName.COLUMN_CONTROLS_WRAPPER} {
440
+ padding: 0 ${tablePadding}px;
441
+ }
442
+
438
443
  &.${ClassName.TABLE_CONTAINER}[data-number-column='true'] {
439
444
  padding-left: ${akEditorTableNumberColumnWidth + tablePadding - 1}px;
440
445
  }
@@ -579,6 +584,8 @@ export const tableStyles = props => {
579
584
  `)}
580
585
  }
581
586
 
587
+ ${floatingColumnControls(props)}
588
+
582
589
  :not(.${ClassName.IS_RESIZING}) .${ClassName.ROW_CONTROLS} {
583
590
  ${HeaderButtonHover(props)}
584
591
  ${HeaderButtonDanger(props)}
@@ -760,6 +767,12 @@ export const tableStyles = props => {
760
767
  .${ClassName.ROW_CONTROLS_WRAPPER} {
761
768
  left: -${tableToolbarSize}px;
762
769
  }
770
+
771
+ .${ClassName.COLUMN_CONTROLS_WRAPPER} {
772
+ position: absolute;
773
+ top: ${tableMarginTop + 1}px;
774
+ }
775
+
763
776
  ${tableWrapperStyles()}
764
777
  }
765
778
 
@@ -89,6 +89,7 @@ export const columnControlsDecorationHeight = 25;
89
89
  export const columnControlsZIndex = akEditorUnitZIndex * 10;
90
90
  export const columnControlsSelectedZIndex = columnControlsZIndex + 1;
91
91
  export const columnResizeHandleZIndex = columnControlsSelectedZIndex + 1;
92
+ export const insertLineWidth = 3;
92
93
  export const resizeHandlerAreaWidth = RESIZE_HANDLE_AREA_DECORATION_GAP / 3;
93
94
  export const resizeLineWidth = 2;
94
95
  export const resizeHandlerZIndex = columnControlsZIndex + akRichMediaResizeZIndex;
@@ -5,7 +5,7 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
5
5
  import { B300, N0, N300, N40A, N60A, Y200, Y50 } from '@atlaskit/theme/colors';
6
6
  import { borderRadius } from '@atlaskit/theme/constants';
7
7
  import { TableCssClassName as ClassName } from '../types';
8
- import { columnControlsDecorationHeight, columnControlsSelectedZIndex, columnControlsZIndex, lineMarkerSize, resizeHandlerAreaWidth, resizeHandlerZIndex, resizeLineWidth, tableBorderColor, tableBorderDeleteColor, tableBorderSelectedColor, tableCellDeleteColor, tableCellHoverDeleteIconBackground, tableCellHoverDeleteIconColor, tableCellSelectedDeleteIconBackground, tableCellSelectedDeleteIconColor, tableDeleteButtonSize, tableHeaderCellBackgroundColor, tableInsertColumnButtonSize, tableOverflowShadowWidth, tableOverflowShadowWidthWide, tableToolbarDeleteColor, tableToolbarSelectedColor, tableToolbarSize } from './consts';
8
+ import { columnControlsDecorationHeight, columnControlsSelectedZIndex, columnControlsZIndex, insertLineWidth, lineMarkerSize, resizeHandlerAreaWidth, resizeHandlerZIndex, resizeLineWidth, tableBorderColor, tableBorderDeleteColor, tableBorderSelectedColor, tableCellDeleteColor, tableCellHoverDeleteIconBackground, tableCellHoverDeleteIconColor, tableCellSelectedDeleteIconBackground, tableCellSelectedDeleteIconColor, tableDeleteButtonSize, tableHeaderCellBackgroundColor, tableInsertColumnButtonSize, tableOverflowShadowWidth, tableOverflowShadowWidthWide, tableToolbarDeleteColor, tableToolbarSelectedColor, tableToolbarSize } from './consts';
9
9
  const InsertLine = (props, cssString) => css`
10
10
  .${ClassName.CONTROLS_INSERT_LINE} {
11
11
  background: ${tableBorderSelectedColor(props)};
@@ -286,6 +286,19 @@ const getFloatingDotOverrides = props => {
286
286
  }
287
287
  ` : '';
288
288
  };
289
+ export const floatingColumnControls = props => {
290
+ return css`
291
+ .${ClassName.COLUMN_DROP_TARGET_CONTROLS} {
292
+ box-sizing: border-box;
293
+ position: absolute;
294
+
295
+ .${ClassName.COLUMN_CONTROLS_INNER} {
296
+ display: flex;
297
+ flex-direction: row;
298
+ }
299
+ }
300
+ `;
301
+ };
289
302
  export const columnControlsDecoration = props => {
290
303
  if (getBooleanFF('platform.editor.table.column-controls-styles-updated')) {
291
304
  return css`
@@ -622,4 +635,117 @@ export const resizeHandle = props => css`
622
635
  height: calc(100% + ${tableToolbarSize + tableCellBorderWidth}px);
623
636
  }
624
637
  }
638
+ `;
639
+ export const insertLine = props => css`
640
+ .${ClassName.TABLE_CONTAINER} {
641
+ td.${ClassName.WITH_FIRST_COLUMN_INSERT_LINE}::before {
642
+ content: ' ';
643
+ position: absolute;
644
+ left: -1px;
645
+ top: -1px;
646
+ width: ${insertLineWidth}px;
647
+ height: calc(100% + ${tableCellBorderWidth * 2}px);
648
+ background-color: ${tableBorderSelectedColor(props)};
649
+ z-index: ${columnControlsZIndex * 2};
650
+ }
651
+
652
+ th.${ClassName.WITH_FIRST_COLUMN_INSERT_LINE}::before {
653
+ content: ' ';
654
+ left: -1px;
655
+ position: absolute;
656
+ width: ${insertLineWidth}px;
657
+ height: calc(100% + ${tableCellBorderWidth * 2}px);
658
+ background-color: ${tableBorderSelectedColor(props)};
659
+ z-index: ${columnControlsZIndex * 2};
660
+ top: -${tableCellBorderWidth}px;
661
+ }
662
+
663
+ td.${ClassName.WITH_COLUMN_INSERT_LINE}::before {
664
+ content: ' ';
665
+ position: absolute;
666
+ left: ${"var(--ds-space-negative-025, -2px)"};
667
+ top: -1px;
668
+ width: ${insertLineWidth}px;
669
+ height: calc(100% + ${tableCellBorderWidth * 2}px);
670
+ background-color: ${tableBorderSelectedColor(props)};
671
+ z-index: ${columnControlsZIndex * 2};
672
+ }
673
+
674
+ th.${ClassName.WITH_COLUMN_INSERT_LINE}::before {
675
+ content: ' ';
676
+ left: ${"var(--ds-space-negative-025, -2px)"};
677
+ position: absolute;
678
+ width: ${insertLineWidth}px;
679
+ height: calc(100% + ${tableCellBorderWidth * 2}px);
680
+ background-color: ${tableBorderSelectedColor(props)};
681
+ z-index: ${columnControlsZIndex * 2};
682
+ top: -${tableCellBorderWidth}px;
683
+ }
684
+
685
+ td.${ClassName.WITH_LAST_COLUMN_INSERT_LINE}::before {
686
+ content: ' ';
687
+ position: absolute;
688
+ right: -1px;
689
+ top: -1px;
690
+ width: ${insertLineWidth}px;
691
+ height: calc(100% + ${tableCellBorderWidth * 2}px);
692
+ background-color: ${tableBorderSelectedColor(props)};
693
+ z-index: ${columnControlsZIndex * 2};
694
+ }
695
+
696
+ th.${ClassName.WITH_LAST_COLUMN_INSERT_LINE}::before {
697
+ content: ' ';
698
+ right: -1px;
699
+ position: absolute;
700
+ width: ${insertLineWidth}px;
701
+ height: calc(100% + ${tableCellBorderWidth * 2}px);
702
+ background-color: ${tableBorderSelectedColor(props)};
703
+ z-index: ${columnControlsZIndex * 2};
704
+ top: -${tableCellBorderWidth}px;
705
+ }
706
+
707
+ td.${ClassName.WITH_ROW_INSERT_LINE}::before {
708
+ content: ' ';
709
+ position: absolute;
710
+ left: ${"var(--ds-space-negative-025, -2px)"};
711
+ top: -1px;
712
+ height: ${insertLineWidth}px;
713
+ width: calc(100% + ${tableCellBorderWidth * 2}px);
714
+ background-color: ${tableBorderSelectedColor(props)};
715
+ z-index: ${columnControlsZIndex * 2};
716
+ }
717
+
718
+ th.${ClassName.WITH_ROW_INSERT_LINE}::before {
719
+ content: ' ';
720
+ left: ${"var(--ds-space-negative-025, -2px)"};
721
+ position: absolute;
722
+ height: ${insertLineWidth}px;
723
+ width: calc(100% + ${tableCellBorderWidth * 2}px);
724
+ background-color: ${tableBorderSelectedColor(props)};
725
+ z-index: ${columnControlsZIndex * 2};
726
+ top: -1px;
727
+ }
728
+
729
+ td.${ClassName.WITH_LAST_ROW_INSERT_LINE}::before {
730
+ content: ' ';
731
+ position: absolute;
732
+ left: ${"var(--ds-space-negative-025, -2px)"};
733
+ bottom: 0;
734
+ height: ${insertLineWidth}px;
735
+ width: calc(100% + 2px);
736
+ background-color: ${tableBorderSelectedColor(props)};
737
+ z-index: ${columnControlsZIndex * 2};
738
+ }
739
+
740
+ th.${ClassName.WITH_LAST_ROW_INSERT_LINE}::before {
741
+ content: ' ';
742
+ left: ${"var(--ds-space-negative-025, -2px)"};
743
+ bottom: 0;
744
+ position: absolute;
745
+ height: ${insertLineWidth}px;
746
+ width: calc(100% + ${tableCellBorderWidth * 2}px);
747
+ background-color: ${tableBorderSelectedColor(props)};
748
+ z-index: ${columnControlsZIndex * 2};
749
+ }
750
+ }
625
751
  `;