@atlaskit/editor-plugin-table 5.7.9 → 5.8.0

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 (105) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/dist/cjs/commands/column-resize.js +155 -0
  4. package/dist/cjs/commands/go-to-next-cell.js +15 -0
  5. package/dist/cjs/commands/selection.js +16 -3
  6. package/dist/cjs/nodeviews/ExternalDropTargets.js +2 -1
  7. package/dist/cjs/plugin.js +2 -1
  8. package/dist/cjs/pm-plugins/drag-and-drop/commands.js +3 -3
  9. package/dist/cjs/pm-plugins/drag-and-drop/plugin.js +2 -1
  10. package/dist/cjs/pm-plugins/keymap.js +9 -0
  11. package/dist/cjs/pm-plugins/table-resizing/event-handlers.js +18 -7
  12. package/dist/cjs/pm-plugins/table-resizing/utils/index.js +6 -0
  13. package/dist/cjs/types.js +8 -1
  14. package/dist/cjs/ui/DragHandle/index.js +1 -1
  15. package/dist/cjs/ui/FloatingDragMenu/DragMenu.js +187 -17
  16. package/dist/cjs/ui/FloatingDragMenu/index.js +4 -2
  17. package/dist/cjs/ui/FloatingDragMenu/styles.js +19 -0
  18. package/dist/cjs/ui/TableFloatingColumnControls/ColumnControls/index.js +2 -2
  19. package/dist/cjs/ui/TableFloatingControls/RowControls/DragControls.js +2 -2
  20. package/dist/cjs/ui/consts.js +2 -1
  21. package/dist/cjs/ui/ui-styles.js +6 -2
  22. package/dist/cjs/utils/decoration.js +14 -4
  23. package/dist/es2019/commands/column-resize.js +149 -0
  24. package/dist/es2019/commands/go-to-next-cell.js +13 -0
  25. package/dist/es2019/commands/selection.js +16 -3
  26. package/dist/es2019/nodeviews/ExternalDropTargets.js +2 -1
  27. package/dist/es2019/plugin.js +2 -1
  28. package/dist/es2019/pm-plugins/drag-and-drop/commands.js +3 -3
  29. package/dist/es2019/pm-plugins/drag-and-drop/plugin.js +2 -1
  30. package/dist/es2019/pm-plugins/keymap.js +10 -1
  31. package/dist/es2019/pm-plugins/table-resizing/event-handlers.js +19 -8
  32. package/dist/es2019/pm-plugins/table-resizing/utils/index.js +1 -1
  33. package/dist/es2019/types.js +8 -1
  34. package/dist/es2019/ui/DragHandle/index.js +1 -1
  35. package/dist/es2019/ui/FloatingDragMenu/DragMenu.js +177 -7
  36. package/dist/es2019/ui/FloatingDragMenu/index.js +4 -2
  37. package/dist/es2019/ui/FloatingDragMenu/styles.js +62 -0
  38. package/dist/es2019/ui/TableFloatingColumnControls/ColumnControls/index.js +2 -2
  39. package/dist/es2019/ui/TableFloatingControls/RowControls/DragControls.js +2 -2
  40. package/dist/es2019/ui/consts.js +2 -1
  41. package/dist/es2019/ui/ui-styles.js +108 -65
  42. package/dist/es2019/utils/decoration.js +14 -4
  43. package/dist/esm/commands/column-resize.js +149 -0
  44. package/dist/esm/commands/go-to-next-cell.js +15 -0
  45. package/dist/esm/commands/selection.js +16 -3
  46. package/dist/esm/nodeviews/ExternalDropTargets.js +2 -1
  47. package/dist/esm/plugin.js +2 -1
  48. package/dist/esm/pm-plugins/drag-and-drop/commands.js +3 -3
  49. package/dist/esm/pm-plugins/drag-and-drop/plugin.js +2 -1
  50. package/dist/esm/pm-plugins/keymap.js +10 -1
  51. package/dist/esm/pm-plugins/table-resizing/event-handlers.js +19 -8
  52. package/dist/esm/pm-plugins/table-resizing/utils/index.js +1 -1
  53. package/dist/esm/types.js +8 -1
  54. package/dist/esm/ui/DragHandle/index.js +1 -1
  55. package/dist/esm/ui/FloatingDragMenu/DragMenu.js +177 -7
  56. package/dist/esm/ui/FloatingDragMenu/index.js +4 -2
  57. package/dist/esm/ui/FloatingDragMenu/styles.js +12 -0
  58. package/dist/esm/ui/TableFloatingColumnControls/ColumnControls/index.js +2 -2
  59. package/dist/esm/ui/TableFloatingControls/RowControls/DragControls.js +2 -2
  60. package/dist/esm/ui/consts.js +2 -1
  61. package/dist/esm/ui/ui-styles.js +7 -3
  62. package/dist/esm/utils/decoration.js +14 -4
  63. package/dist/types/commands/column-resize.d.ts +5 -0
  64. package/dist/types/pm-plugins/drag-and-drop/commands.d.ts +1 -1
  65. package/dist/types/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  66. package/dist/types/types.d.ts +7 -0
  67. package/dist/types/ui/FloatingDragMenu/DragMenu.d.ts +1 -2
  68. package/dist/types/ui/FloatingDragMenu/index.d.ts +3 -2
  69. package/dist/types/ui/FloatingDragMenu/styles.d.ts +3 -0
  70. package/dist/types/ui/consts.d.ts +1 -1
  71. package/dist/types/utils/decoration.d.ts +2 -2
  72. package/dist/types-ts4.5/commands/column-resize.d.ts +5 -0
  73. package/dist/types-ts4.5/pm-plugins/drag-and-drop/commands.d.ts +1 -1
  74. package/dist/types-ts4.5/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  75. package/dist/types-ts4.5/types.d.ts +7 -0
  76. package/dist/types-ts4.5/ui/FloatingDragMenu/DragMenu.d.ts +1 -2
  77. package/dist/types-ts4.5/ui/FloatingDragMenu/index.d.ts +3 -2
  78. package/dist/types-ts4.5/ui/FloatingDragMenu/styles.d.ts +3 -0
  79. package/dist/types-ts4.5/ui/consts.d.ts +1 -1
  80. package/dist/types-ts4.5/utils/decoration.d.ts +2 -2
  81. package/package.json +8 -4
  82. package/src/__tests__/unit/analytics.ts +5 -1
  83. package/src/__tests__/unit/ui/FloatingDragMenu.tsx +295 -0
  84. package/src/__tests__/unit/ui/RowDragControls.tsx +5 -4
  85. package/src/commands/column-resize.ts +257 -0
  86. package/src/commands/go-to-next-cell.ts +21 -0
  87. package/src/commands/selection.ts +19 -2
  88. package/src/nodeviews/ExternalDropTargets.tsx +1 -0
  89. package/src/plugin.tsx +1 -0
  90. package/src/pm-plugins/drag-and-drop/commands.ts +3 -2
  91. package/src/pm-plugins/drag-and-drop/plugin.ts +10 -4
  92. package/src/pm-plugins/keymap.ts +35 -0
  93. package/src/pm-plugins/table-resizing/event-handlers.ts +33 -21
  94. package/src/pm-plugins/table-resizing/utils/index.ts +1 -0
  95. package/src/types.ts +9 -0
  96. package/src/ui/DragHandle/index.tsx +1 -1
  97. package/src/ui/FloatingDragMenu/DragMenu.tsx +226 -7
  98. package/src/ui/FloatingDragMenu/index.tsx +4 -1
  99. package/src/ui/FloatingDragMenu/styles.ts +71 -0
  100. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +35 -37
  101. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +33 -33
  102. package/src/ui/consts.ts +6 -1
  103. package/src/ui/ui-styles.ts +115 -64
  104. package/src/utils/decoration.ts +27 -8
  105. package/tsconfig.app.json +3 -0
@@ -4,7 +4,10 @@ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
4
  import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
5
5
  import { TableMap } from '@atlaskit/editor-tables/table-map';
6
6
  import { goToNextCell as baseGotoNextCell, findTable } from '@atlaskit/editor-tables/utils';
7
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
7
8
  import { insertRowWithAnalytics } from '../commands-with-analytics';
9
+ import { getPluginState as getResizePluginState, createCommand as tableResizingPluginCreateCommand } from '../pm-plugins/table-resizing/plugin-factory';
10
+ import { hideResizeHandleLine } from './hover';
8
11
  const TAB_FORWARD_DIRECTION = 1;
9
12
  const TAB_BACKWARD_DIRECTION = -1;
10
13
  export const goToNextCell = editorAnalyticsAPI => direction => (state, dispatch) => {
@@ -12,6 +15,16 @@ export const goToNextCell = editorAnalyticsAPI => direction => (state, dispatch)
12
15
  if (!table) {
13
16
  return false;
14
17
  }
18
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
19
+ var _getResizePluginState;
20
+ const isColumnResizing = !!((_getResizePluginState = getResizePluginState(state)) !== null && _getResizePluginState !== void 0 && _getResizePluginState.dragging);
21
+ if (isColumnResizing) {
22
+ tableResizingPluginCreateCommand({
23
+ type: 'STOP_RESIZING'
24
+ }, originalTr => (state.tr || originalTr).setMeta('scrollIntoView', false))(state, dispatch);
25
+ hideResizeHandleLine()(state, dispatch);
26
+ }
27
+ }
15
28
  const map = TableMap.get(table.node);
16
29
  const {
17
30
  tableCell,
@@ -3,7 +3,9 @@ import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
3
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
4
4
  import { TableMap } from '@atlaskit/editor-tables/table-map';
5
5
  import { findTable, isColumnSelected, isRowSelected, isTableSelected, selectedRect } from '@atlaskit/editor-tables/utils';
6
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
6
7
  import { selectColumn, selectRow } from '../commands/misc';
8
+ import { getPluginState as getResizePluginState } from '../pm-plugins/table-resizing/plugin-factory';
7
9
  import { getClosestSelectionRect } from '../toolbar';
8
10
  export let TableSelectionDirection = /*#__PURE__*/function (TableSelectionDirection) {
9
11
  TableSelectionDirection["TopToBottom"] = "TopToBottom";
@@ -175,9 +177,14 @@ const arrowLeftFromText = editorSelectionAPI => selection => (state, dispatch) =
175
177
  const {
176
178
  $from
177
179
  } = selection;
180
+ let isColumnResizing = false;
181
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
182
+ const columResizePluginState = getResizePluginState(state) || {};
183
+ isColumnResizing = Boolean(columResizePluginState === null || columResizePluginState === void 0 ? void 0 : columResizePluginState.dragging);
184
+ }
178
185
  if (isSelectionAtStartOfTable($from, selection) && $from.parent.type.name === 'paragraph' && $from.depth === table.depth + 3 &&
179
186
  // + 3 for: row, cell & paragraph nodes
180
- editorSelectionAPI) {
187
+ editorSelectionAPI && !isColumnResizing) {
181
188
  const selectionState = editorSelectionAPI.sharedState.currentState() || {};
182
189
  if ((selectionState === null || selectionState === void 0 ? void 0 : selectionState.selectionRelativeToNode) === RelativeSelectionPos.Before) {
183
190
  // we have a text selection at start of first table cell, directly inside a top level paragraph,
@@ -202,8 +209,14 @@ const arrowRightFromText = editorSelectionAPI => selection => (state, dispatch)
202
209
  const {
203
210
  $to
204
211
  } = selection;
205
- if (isSelectionAtEndOfTable($to, selection) && $to.parent.type.name === 'paragraph' && $to.depth === table.depth + 3 // + 3 for: row, cell & paragraph nodes
206
- ) {
212
+ let isColumnResizing = false;
213
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
214
+ const columResizePluginState = getResizePluginState(state) || {};
215
+ isColumnResizing = Boolean(columResizePluginState === null || columResizePluginState === void 0 ? void 0 : columResizePluginState.dragging);
216
+ }
217
+ if (isSelectionAtEndOfTable($to, selection) && $to.parent.type.name === 'paragraph' && $to.depth === table.depth + 3 &&
218
+ // + 3 for: row, cell & paragraph nodes
219
+ !isColumnResizing) {
207
220
  // we have a text selection at end of last table cell, directly inside a top level paragraph,
208
221
  // and want to set a full table cell selection
209
222
  return selectFullTable(editorSelectionAPI)({
@@ -44,7 +44,8 @@ export const ExternalDropTargets = ({
44
44
  top: `-${dropTargetExtendedWidth - tableMarginTop}px`,
45
45
  pointerEvents: 'auto',
46
46
  zIndex: `${dropTargetsZIndex}`
47
- }
47
+ },
48
+ "data-testid": "table-floating-column-extended-drop-targets"
48
49
  }, /*#__PURE__*/React.createElement("div", {
49
50
  style: {
50
51
  display: 'flex',
@@ -359,7 +359,8 @@ const tablesPlugin = ({
359
359
  canDrag: dragAndDropState === null || dragAndDropState === void 0 ? void 0 : dragAndDropState.canDrag,
360
360
  getEditorContainerWidth: defaultGetEditorContainerWidth,
361
361
  editorAnalyticsAPI: editorAnalyticsAPI,
362
- stickyHeaders: stickyHeader
362
+ stickyHeaders: stickyHeader,
363
+ pluginConfig: pluginConfig
363
364
  }), allowControls && !isDragAndDropEnabled && !isResizing && /*#__PURE__*/React.createElement(FloatingDeleteButton, {
364
365
  editorView: editorView,
365
366
  selection: editorView.state.selection,
@@ -15,7 +15,7 @@ export const getDecorations = state => {
15
15
  return ((_pluginKey$getState = pluginKey.getState(state)) === null || _pluginKey$getState === void 0 ? void 0 : _pluginKey$getState.decorationSet) || DecorationSet.empty;
16
16
  };
17
17
  export const updatePluginStateDecorations = (state, decorations, key) => updateDecorations(state.doc, getDecorations(state), decorations, key);
18
- export const setDropTarget = (type, index, tr) => createCommand(state => {
18
+ export const setDropTarget = (type, index, hasMergedCells, tr) => createCommand(state => {
19
19
  const {
20
20
  dropTargetType,
21
21
  dropTargetIndex
@@ -25,9 +25,9 @@ export const setDropTarget = (type, index, tr) => createCommand(state => {
25
25
  }
26
26
  let decorationSet = DecorationSet.empty;
27
27
  if (type === 'column') {
28
- decorationSet = updatePluginStateDecorations(state, createColumnInsertLine(index, state.selection), TableDecorations.COLUMN_INSERT_LINE);
28
+ decorationSet = updatePluginStateDecorations(state, createColumnInsertLine(index, state.selection, hasMergedCells), TableDecorations.COLUMN_INSERT_LINE);
29
29
  } else if (type === 'row') {
30
- decorationSet = updatePluginStateDecorations(state, createRowInsertLine(index, state.selection), TableDecorations.ROW_INSERT_LINE);
30
+ decorationSet = updatePluginStateDecorations(state, createRowInsertLine(index, state.selection, hasMergedCells), TableDecorations.ROW_INSERT_LINE);
31
31
  }
32
32
  return {
33
33
  type: DragAndDropActionType.SET_DROP_TARGET,
@@ -137,7 +137,8 @@ export const createPlugin = (dispatch, eventDispatcher, editorAnalyticsAPI) => {
137
137
  targetAdjustedIndex
138
138
  } = data;
139
139
  const dropTargetType = sourceType === 'table-row' ? DropTargetType.ROW : DropTargetType.COLUMN;
140
- setDropTarget(dropTargetType, targetAdjustedIndex)(editorView.state, editorView.dispatch);
140
+ const hasMergedCells = hasMergedCellsInBetween([targetAdjustedIndex - 1, targetAdjustedIndex], dropTargetType)(editorView.state.selection);
141
+ setDropTarget(dropTargetType, targetAdjustedIndex, hasMergedCells)(editorView.state, editorView.dispatch);
141
142
  },
142
143
  onDrop(event) {
143
144
  var _cell$row, _cell$col;
@@ -1,9 +1,11 @@
1
1
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
- import { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, backspace, bindKeymapWithCommand, deleteColumn, deleteRow, moveColumnLeft, moveColumnRight, moveRowDown, moveRowUp, nextCell, previousCell, toggleTable } from '@atlaskit/editor-common/keymaps';
2
+ import { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, increaseMediaSize, moveColumnLeft, moveColumnRight, moveLeft, moveRight, moveRowDown, moveRowUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
3
3
  import { chainCommands } from '@atlaskit/editor-prosemirror/commands';
4
4
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
5
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
5
6
  import { createTable, goToNextCell, moveCursorBackward, triggerUnlessTableHeader } from '../commands';
6
7
  import { addRowAroundSelection, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut, deleteTableIfSelectedWithAnalytics, emptyMultipleCellsWithAnalytics } from '../commands-with-analytics';
8
+ import { activateNextResizeArea, changeColumnWidthByStep, initiateKeyboardColumnResizing } from '../commands/column-resize';
7
9
  import { addColumnAfter as addColumnAfterCommand, addColumnBefore as addColumnBeforeCommand } from '../commands/insert';
8
10
  import { moveSourceWithAnalyticsViaShortcut } from '../pm-plugins/drag-and-drop/commands-with-analytics';
9
11
  import { withEditorAnalyticsAPI } from '../utils/analytics';
@@ -40,6 +42,13 @@ export function keymapPlugin(getEditorContainerWidth, editorAnalyticsAPI, dragAn
40
42
  bindKeymapWithCommand(deleteColumn.common, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut(editorAnalyticsAPI), list);
41
43
  bindKeymapWithCommand(deleteRow.common, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut(editorAnalyticsAPI), list);
42
44
  }
45
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
46
+ bindKeymapWithCommand(startColumnResizing.common, initiateKeyboardColumnResizing, list);
47
+ bindKeymapWithCommand(moveRight.common, activateNextResizeArea(1), list);
48
+ bindKeymapWithCommand(moveLeft.common, activateNextResizeArea(-1), list);
49
+ bindKeymapWithCommand(decreaseMediaSize.common, changeColumnWidthByStep(-10, getEditorContainerWidth), list);
50
+ bindKeymapWithCommand(increaseMediaSize.common, changeColumnWidthByStep(10, getEditorContainerWidth), list);
51
+ }
43
52
  return keymap(list);
44
53
  }
45
54
  export default keymapPlugin;
@@ -11,7 +11,7 @@ import { getSelectedColumnIndexes } from '../../utils';
11
11
  import { META_KEYS } from '../table-analytics';
12
12
  import { evenColumns, setDragging, stopResizing } from './commands';
13
13
  import { getPluginState } from './plugin-factory';
14
- import { currentColWidth, getLayoutSize, getResizeState, pointsAtCell, resizeColumn, updateControls } from './utils';
14
+ import { currentColWidth, getLayoutSize, getResizeState, getTableMaxWidth, pointsAtCell, resizeColumn, updateControls } from './utils';
15
15
  export const handleMouseDown = (view, event, localResizeHandlePos, getEditorContainerWidth, getEditorFeatureFlags, editorAnalyticsAPI) => {
16
16
  const {
17
17
  state,
@@ -37,13 +37,24 @@ export const handleMouseDown = (view, event, localResizeHandlePos, getEditorCont
37
37
  if (dom && dom.nodeName !== 'TABLE') {
38
38
  dom = dom.closest('table');
39
39
  }
40
- const containerWidth = getEditorContainerWidth();
41
- const parentWidth = getParentNodeWidth(start, state, containerWidth);
42
- let maxSize = getBooleanFF('platform.editor.custom-table-width') ? parentWidth ||
43
- // its safe to reference table width from node as this will not have changed
44
- originalTable.attrs.width || getLayoutSize(dom.getAttribute('data-layout'), containerWidth.width, {}) : parentWidth || getLayoutSize(dom.getAttribute('data-layout'), containerWidth.width, {});
45
- if (originalTable.attrs.isNumberColumnEnabled) {
46
- maxSize -= akEditorTableNumberColumnWidth;
40
+ let maxSize;
41
+ if (!getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
42
+ const containerWidth = getEditorContainerWidth();
43
+ const parentWidth = getParentNodeWidth(start, state, containerWidth);
44
+ maxSize = getBooleanFF('platform.editor.custom-table-width') ? parentWidth ||
45
+ // its safe to reference table width from node as this will not have changed
46
+ originalTable.attrs.width || getLayoutSize(dom.getAttribute('data-layout'), containerWidth.width, {}) : parentWidth || getLayoutSize(dom.getAttribute('data-layout'), containerWidth.width, {});
47
+ if (originalTable.attrs.isNumberColumnEnabled) {
48
+ maxSize -= akEditorTableNumberColumnWidth;
49
+ }
50
+ } else {
51
+ maxSize = getTableMaxWidth({
52
+ table: originalTable,
53
+ tableStart: start,
54
+ state,
55
+ layout: originalTable.attrs.layout,
56
+ getEditorContainerWidth
57
+ });
47
58
  }
48
59
  const resizeState = getResizeState({
49
60
  minWidth: tableCellMinWidth,
@@ -3,7 +3,7 @@ export { contentWidth } from './content-width';
3
3
  export { getColumnStateFromDOM, getFreeSpace, getCellsRefsInColumn, calculateColumnWidth, addContainerLeftRightPadding } from './column-state';
4
4
  export { growColumn, shrinkColumn, reduceSpace } from './resize-logic';
5
5
  export { getResizeState, updateColgroup, getTotalWidth, evenAllColumnsWidths, bulkColumnsResize, areColumnsEven, adjustColumnsWidths } from './resize-state';
6
- export { getLayoutSize, getDefaultLayoutMaxWidth, pointsAtCell, currentColWidth, domCellAround } from './misc';
6
+ export { getLayoutSize, getDefaultLayoutMaxWidth, pointsAtCell, currentColWidth, domCellAround, getTableMaxWidth } from './misc';
7
7
  export { updateControls, isClickNear, getResizeCellPos } from './dom';
8
8
  export { scale, scaleWithParent, scaleTable, previewScaleTable } from './scale-table';
9
9
  export { resizeColumn } from './resize-column';
@@ -97,6 +97,8 @@ export const TableCssClassName = {
97
97
  DRAG_HANDLE_DISABLED: `${tablePrefixSelector}-drag-handle-disabled`,
98
98
  /** minimised handle class */
99
99
  DRAG_HANDLE_MINIMISED: `${tablePrefixSelector}-drag-handle-minimised`,
100
+ DRAG_SUBMENU: `${tablePrefixSelector}-drag-submenu`,
101
+ DRAG_SUBMENU_ICON: `${tablePrefixSelector}-drag-submenu-icon`,
100
102
  /** Other classes */
101
103
  NUMBERED_COLUMN: `${tablePrefixSelector}-numbered-column`,
102
104
  NUMBERED_COLUMN_BUTTON: `${tablePrefixSelector}-numbered-column__button`,
@@ -132,12 +134,17 @@ export const TableCssClassName = {
132
134
  TOP_LEFT_CELL: 'table > tbody > tr:nth-child(2) > td:nth-child(1)',
133
135
  LAST_ITEM_IN_CELL: `${tablePrefixSelector}-last-item-in-cell`,
134
136
  WITH_COLUMN_INSERT_LINE: `${tablePrefixSelector}-column-insert-line`,
137
+ WITH_COLUMN_INSERT_LINE_INACTIVE: `${tablePrefixSelector}-column-insert-line__inactive`,
135
138
  WITH_FIRST_COLUMN_INSERT_LINE: `${tablePrefixSelector}-first-column-insert-line`,
139
+ WITH_FIRST_COLUMN_INSERT_LINE_INACTIVE: `${tablePrefixSelector}-first-column-insert-line__inactive`,
136
140
  WITH_LAST_COLUMN_INSERT_LINE: `${tablePrefixSelector}-last-column-insert-line`,
141
+ WITH_LAST_COLUMN_INSERT_LINE_INACTIVE: `${tablePrefixSelector}-last-column-insert-line__inactive`,
137
142
  WITH_RESIZE_LINE: `${tablePrefixSelector}-column-resize-line`,
138
143
  WITH_RESIZE_LINE_LAST_COLUMN: `${tablePrefixSelector}-column-resize-line-last-column`,
139
144
  WITH_ROW_INSERT_LINE: `${tablePrefixSelector}-row-insert-line`,
140
- WITH_LAST_ROW_INSERT_LINE: `${tablePrefixSelector}-last-row-insert-line`
145
+ WITH_ROW_INSERT_LINE_INACTIVE: `${tablePrefixSelector}-row-insert-line__inactive`,
146
+ WITH_LAST_ROW_INSERT_LINE: `${tablePrefixSelector}-last-row-insert-line`,
147
+ WITH_LAST_ROW_INSERT_LINE_INACTIVE: `${tablePrefixSelector}-last-row-insert-line__inactive`
141
148
  };
142
149
  export let ShadowEvent = /*#__PURE__*/function (ShadowEvent) {
143
150
  ShadowEvent["SHOW_BEFORE_SHADOW"] = "showBeforeShadow";
@@ -109,7 +109,7 @@ export const DragHandle = ({
109
109
  style: {
110
110
  transform: direction === 'column' ? 'none' : 'rotate(90deg)'
111
111
  },
112
- "data-testid": "table-floating-column-controls-drag-handle",
112
+ "data-testid": "table-drag-handle-button",
113
113
  onMouseOver: onMouseOver,
114
114
  onMouseOut: onMouseOut,
115
115
  onMouseUp: e => {
@@ -1,15 +1,29 @@
1
+ /* eslint-disable @atlaskit/design-system/prefer-primitives */
1
2
  /** @jsx jsx */
3
+ import { useState } from 'react';
2
4
  import { jsx } from '@emotion/react';
5
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
6
+ import { DropdownMenuSharedCssClassName } from '@atlaskit/editor-common/styles';
7
+ import { backgroundPaletteTooltipMessages, cellBackgroundColorPalette, ColorPalette } from '@atlaskit/editor-common/ui-color';
3
8
  import { ArrowKeyNavigationType, DropdownMenu } from '@atlaskit/editor-common/ui-menu';
9
+ import { closestElement } from '@atlaskit/editor-common/utils';
10
+ import { hexToEditorBackgroundPaletteColor } from '@atlaskit/editor-palette';
4
11
  import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
5
12
  import { TableMap } from '@atlaskit/editor-tables/table-map';
6
13
  import { findCellRectClosestToPos, getSelectionRect, isSelectionType } from '@atlaskit/editor-tables/utils';
14
+ import EditorBackgroundColorIcon from '@atlaskit/icon/glyph/editor/background-color';
15
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
16
+ import Toggle from '@atlaskit/toggle';
7
17
  import { clearHoverSelection, hoverColumns, hoverRows } from '../../commands';
18
+ import { setColorWithAnalytics, toggleHeaderColumnWithAnalytics, toggleHeaderRowWithAnalytics, toggleNumberColumnWithAnalytics } from '../../commands-with-analytics';
8
19
  import { toggleDragMenu } from '../../pm-plugins/drag-and-drop/commands';
9
20
  import { getPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
10
- import { getMergedCellsPositions, getSelectedColumnIndexes, getSelectedRowIndexes, hasMergedCellsInColumn, hasMergedCellsInRow } from '../../utils';
21
+ import { getPluginState as getTablePluginState } from '../../pm-plugins/plugin-factory';
22
+ import { TableCssClassName as ClassName } from '../../types';
23
+ import { checkIfHeaderColumnEnabled, checkIfHeaderRowEnabled, checkIfNumberColumnEnabled, getMergedCellsPositions, getSelectedColumnIndexes, getSelectedRowIndexes, hasMergedCellsInColumn, hasMergedCellsInRow } from '../../utils';
11
24
  import { getDragMenuConfig } from '../../utils/drag-menu';
12
25
  import { dragMenuDropdownWidth } from '../consts';
26
+ import { cellColourPreviewStyles, dragMenuBackgroundColorStyles, toggleStyles } from './styles';
13
27
  const groupedDragMenuConfig = [['add_row_above', 'add_row_below', 'add_column_left', 'add_column_right', 'distribute_columns', 'clear_cells', 'delete_row', 'delete_column'], ['move_column_left', 'move_column_right', 'move_row_up', 'move_row_down'], ['sort_column_asc', 'sort_column_desc']];
14
28
  const convertToDropdownItems = dragMenuConfig => {
15
29
  let menuItemsArr = [...Array(groupedDragMenuConfig.length)].map(() => []);
@@ -28,7 +42,6 @@ const convertToDropdownItems = dragMenuConfig => {
28
42
  isDisabled: item.disabled,
29
43
  elemBefore: item.icon ? jsx("div", {
30
44
  style: {
31
- marginRight: "var(--ds-space-negative-075, -6px)",
32
45
  display: 'flex'
33
46
  }
34
47
  }, jsx(item.icon, {
@@ -63,9 +76,10 @@ export const DragMenu = ({
63
76
  targetCellPosition,
64
77
  getEditorContainerWidth,
65
78
  canDrag,
66
- editorAnalyticsAPI
79
+ editorAnalyticsAPI,
80
+ pluginConfig
67
81
  }) => {
68
- const tableMap = tableNode ? TableMap.get(tableNode) : undefined;
82
+ var _pluginConfig$allowBa;
69
83
  const {
70
84
  state,
71
85
  dispatch
@@ -73,19 +87,133 @@ export const DragMenu = ({
73
87
  const {
74
88
  selection
75
89
  } = state;
90
+ const tableMap = tableNode ? TableMap.get(tableNode) : undefined;
91
+ const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);
76
92
  const selectionRect = isSelectionType(selection, 'cell') ? getSelectionRect(selection) : findCellRectClosestToPos(selection.$from);
77
93
  const hasMergedCells = direction === 'row' ? hasMergedCellsInRow : hasMergedCellsInColumn;
78
94
  const shouldMoveDisabled = index !== undefined && hasMergedCells(index)(selection);
79
95
  const hasMergedCellsInTable = getMergedCellsPositions(state.tr).length > 0;
96
+ const allowBackgroundColor = (_pluginConfig$allowBa = pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.allowBackgroundColor) !== null && _pluginConfig$allowBa !== void 0 ? _pluginConfig$allowBa : false;
80
97
  const dragMenuConfig = getDragMenuConfig(direction, getEditorContainerWidth, !!canDrag && !shouldMoveDisabled, hasMergedCellsInTable, editorView, tableMap, index, targetCellPosition, selectionRect, editorAnalyticsAPI);
81
98
  const {
82
99
  menuItems,
83
100
  menuCallback
84
101
  } = convertToDropdownItems(dragMenuConfig);
102
+ const handleSubMenuRef = ref => {
103
+ const parent = closestElement(editorView.dom, '.fabric-editor-popup-scroll-parent');
104
+ if (!(parent && ref)) {
105
+ return;
106
+ }
107
+ const boundariesRect = parent.getBoundingClientRect();
108
+ const rect = ref.getBoundingClientRect();
109
+ if (rect.left + rect.width > boundariesRect.width) {
110
+ ref.style.left = `-${rect.width}px`;
111
+ }
112
+ };
113
+ const setColor = color => {
114
+ const {
115
+ targetCellPosition
116
+ } = getTablePluginState(editorView.state);
117
+ const {
118
+ state,
119
+ dispatch
120
+ } = editorView;
121
+ setColorWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.CONTEXT_MENU, color, targetCellPosition)(state, dispatch);
122
+ closeMenu();
123
+ setIsSubmenuOpen(false);
124
+ };
125
+ const createBackgroundColorMenuItem = () => {
126
+ var _node$attrs;
127
+ const {
128
+ targetCellPosition
129
+ } = getTablePluginState(editorView.state);
130
+ const node = targetCellPosition ? state.doc.nodeAt(targetCellPosition) : null;
131
+ const background = hexToEditorBackgroundPaletteColor((node === null || node === void 0 ? void 0 : (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.background) || '#ffffff');
132
+ return {
133
+ content: 'Background color',
134
+ value: {
135
+ name: 'background'
136
+ },
137
+ elemBefore: jsx(EditorBackgroundColorIcon, {
138
+ label: 'background color',
139
+ size: "medium"
140
+ }),
141
+ elemAfter: jsx("div", {
142
+ className: DropdownMenuSharedCssClassName.SUBMENU,
143
+ css: dragMenuBackgroundColorStyles
144
+ }, jsx("div", {
145
+ css: cellColourPreviewStyles(background),
146
+ className: ClassName.DRAG_SUBMENU_ICON
147
+ }), isSubmenuOpen && jsx("div", {
148
+ className: ClassName.DRAG_SUBMENU,
149
+ ref: handleSubMenuRef
150
+ }, jsx(ColorPalette, {
151
+ cols: 7,
152
+ onClick: setColor,
153
+ selectedColor: background,
154
+ paletteOptions: {
155
+ palette: cellBackgroundColorPalette,
156
+ paletteColorTooltipMessages: backgroundPaletteTooltipMessages,
157
+ hexToPaletteColor: hexToEditorBackgroundPaletteColor
158
+ }
159
+ })))
160
+ };
161
+ };
162
+ const toggleHeaderColumn = () => {
163
+ toggleHeaderColumnWithAnalytics(editorAnalyticsAPI)(state, dispatch);
164
+ };
165
+ const toggleHeaderRow = () => {
166
+ toggleHeaderRowWithAnalytics(editorAnalyticsAPI)(state, dispatch);
167
+ };
168
+ const toggleRowNumbers = () => {
169
+ toggleNumberColumnWithAnalytics(editorAnalyticsAPI)(state, dispatch);
170
+ };
171
+ const createhHeaderRowColumnMenuItem = direction => {
172
+ return direction === 'column' ? {
173
+ content: 'Header column',
174
+ value: {
175
+ name: 'header_column'
176
+ },
177
+ elemAfter: jsx("div", {
178
+ css: toggleStyles
179
+ }, jsx(Toggle, {
180
+ id: "toggle-header-column",
181
+ onChange: toggleHeaderColumn,
182
+ isChecked: checkIfHeaderColumnEnabled(selection)
183
+ }))
184
+ } : {
185
+ content: 'Header row',
186
+ value: {
187
+ name: 'header_row'
188
+ },
189
+ elemAfter: jsx("div", {
190
+ css: toggleStyles
191
+ }, jsx(Toggle, {
192
+ id: "toggle-header-row",
193
+ onChange: toggleHeaderRow,
194
+ isChecked: checkIfHeaderRowEnabled(selection)
195
+ }))
196
+ };
197
+ };
198
+ const createRowNumbersMenuItem = () => {
199
+ return {
200
+ content: 'Row numbers',
201
+ value: {
202
+ name: 'row_numbers'
203
+ },
204
+ elemAfter: jsx("div", {
205
+ css: toggleStyles
206
+ }, jsx(Toggle, {
207
+ id: "toggle-row-numbers",
208
+ onChange: toggleRowNumbers,
209
+ isChecked: checkIfNumberColumnEnabled(selection)
210
+ }))
211
+ };
212
+ };
85
213
 
86
214
  /**
87
215
  * This function is to check if the menu should be closed or not.
88
- * As when continously clicking on drag handle on different rows/columns,
216
+ * As when continously clicking on tyle handle on different rows/columns,
89
217
  * should open the menu corresponding to the position of the drag handle.
90
218
  * @returns true when the menu should be closed, false otherwise
91
219
  */
@@ -119,13 +247,34 @@ export const DragMenu = ({
119
247
  }) => {
120
248
  var _menuCallback$item$va;
121
249
  (_menuCallback$item$va = menuCallback[item.value.name]) === null || _menuCallback$item$va === void 0 ? void 0 : _menuCallback$item$va.call(menuCallback, state, dispatch);
122
- closeMenu();
250
+ switch (item.value.name) {
251
+ case 'header_column':
252
+ toggleHeaderColumn();
253
+ break;
254
+ case 'header_row':
255
+ toggleHeaderRow();
256
+ break;
257
+ case 'row_numbers':
258
+ toggleRowNumbers();
259
+ break;
260
+ default:
261
+ break;
262
+ }
263
+ if (['header_column', 'header_row', 'row_numbers', 'background'].indexOf(item.value.name) <= -1) {
264
+ closeMenu();
265
+ }
123
266
  };
124
267
  const handleItemMouseEnter = ({
125
268
  item
126
269
  }) => {
127
270
  var _item$value$name;
128
- if (!selectionRect || !((_item$value$name = item.value.name) !== null && _item$value$name !== void 0 && _item$value$name.startsWith('delete'))) {
271
+ if (!selectionRect) {
272
+ return;
273
+ }
274
+ if (item.value.name === 'background' && !isSubmenuOpen) {
275
+ setIsSubmenuOpen(true);
276
+ }
277
+ if (!((_item$value$name = item.value.name) !== null && _item$value$name !== void 0 && _item$value$name.startsWith('delete'))) {
129
278
  return;
130
279
  }
131
280
  (item.value.name === 'delete_column' ? hoverColumns(getSelectedColumnIndexes(selectionRect), true) : hoverRows(getSelectedRowIndexes(selectionRect), true))(state, dispatch);
@@ -133,6 +282,9 @@ export const DragMenu = ({
133
282
  const handleItemMouseLeave = ({
134
283
  item
135
284
  }) => {
285
+ if (item.value.name === 'background' && isSubmenuOpen) {
286
+ setIsSubmenuOpen(false);
287
+ }
136
288
  if (['sort_column_asc', 'sort_column_desc', 'delete_column', 'delete_row'].indexOf(item.value.name) > -1) {
137
289
  clearHoverSelection()(state, dispatch);
138
290
  }
@@ -140,6 +292,24 @@ export const DragMenu = ({
140
292
  if (!menuItems) {
141
293
  return null;
142
294
  }
295
+ if (allowBackgroundColor && getBooleanFF('platform.editor.table.new-cell-context-menu-styling')) {
296
+ menuItems[0].items.unshift(createBackgroundColorMenuItem());
297
+ }
298
+
299
+ // If first row, add toggle for Hearder row, default is true
300
+ // If first column, add toggle for Header column, default is false
301
+ if (getBooleanFF('platform.editor.table.new-cell-context-menu-styling') && index === 0) {
302
+ menuItems.push({
303
+ items: [createhHeaderRowColumnMenuItem(direction)]
304
+ });
305
+ }
306
+
307
+ // All rows, add toggle for numbered rows, default is false
308
+ if (getBooleanFF('platform.editor.table.new-cell-context-menu-styling') && direction === 'row') {
309
+ index === 0 ? menuItems[menuItems.length - 1].items.push(createRowNumbersMenuItem()) : menuItems.push({
310
+ items: [createRowNumbersMenuItem()]
311
+ });
312
+ }
143
313
  return jsx(DropdownMenu, {
144
314
  mountTo: mountPoint
145
315
  //This needs be removed when the a11y is completely handled
@@ -17,7 +17,8 @@ const FloatingDragMenu = ({
17
17
  getEditorContainerWidth,
18
18
  canDrag,
19
19
  editorAnalyticsAPI,
20
- stickyHeaders
20
+ stickyHeaders,
21
+ pluginConfig
21
22
  }) => {
22
23
  if (!isOpen || !targetCellPosition || editorView.state.doc.nodeSize <= targetCellPosition) {
23
24
  return null;
@@ -56,7 +57,8 @@ const FloatingDragMenu = ({
56
57
  targetCellPosition: targetCellPosition,
57
58
  getEditorContainerWidth: getEditorContainerWidth,
58
59
  canDrag: canDrag,
59
- editorAnalyticsAPI: editorAnalyticsAPI
60
+ editorAnalyticsAPI: editorAnalyticsAPI,
61
+ pluginConfig: pluginConfig
60
62
  }));
61
63
  };
62
64
  FloatingDragMenu.displayName = 'FloatingDragMenu';
@@ -0,0 +1,62 @@
1
+ import { css } from '@emotion/react';
2
+ import { tableBackgroundBorderColor } from '@atlaskit/adf-schema';
3
+ import { N60A, N90 } from '@atlaskit/theme/colors';
4
+ import { TableCssClassName as ClassName } from '../../types';
5
+ import { dragMenuDropdownWidth } from '../consts';
6
+ export const cellColourPreviewStyles = selectedColor => css`
7
+ &::before {
8
+ background: ${selectedColor};
9
+ }
10
+ `;
11
+ export const dragMenuBackgroundColorStyles = css`
12
+ .${ClassName.DRAG_SUBMENU} {
13
+ border-radius: ${"var(--ds-border-radius, 3px)"};
14
+ background: ${"var(--ds-surface-overlay, white)"};
15
+ box-shadow: ${`var(--ds-shadow-overlay, ${`0 4px 8px -2px ${N60A}, 0 0 1px ${N60A}`})`};
16
+ display: block;
17
+ position: absolute;
18
+ top: 0;
19
+ left: ${dragMenuDropdownWidth}px;
20
+ padding: ${"var(--ds-space-100, 8px)"};
21
+
22
+ > div {
23
+ padding: 0;
24
+ }
25
+ }
26
+
27
+ .${ClassName.DRAG_SUBMENU_ICON} {
28
+ display: flex;
29
+
30
+ &::before {
31
+ content: '';
32
+ display: block;
33
+ border: 1px solid ${tableBackgroundBorderColor};
34
+ border-radius: ${"var(--ds-border-radius, 3px)"};
35
+ width: 14px;
36
+ height: 14px;
37
+ }
38
+
39
+ &::after {
40
+ content: '›';
41
+ margin-left: ${"var(--ds-space-050, 4px)"};
42
+ line-height: 14px;
43
+ color: ${`var(--ds-icon, ${N90})`};
44
+ }
45
+ }
46
+ `;
47
+ export const toggleStyles = css`
48
+ display: flex;
49
+ input[type='checkbox'] {
50
+ width: 30px;
51
+ height: 14px;
52
+ pointer-events: initial;
53
+ cursor: pointer;
54
+ }
55
+ > label {
56
+ margin: 0px;
57
+ pointer-events: none;
58
+ > span {
59
+ pointer-events: none;
60
+ }
61
+ }
62
+ `;
@@ -150,7 +150,7 @@ export const ColumnControls = ({
150
150
 
151
151
  // this indexes are used to calculate the drag and drop source
152
152
  const indexes = isColumnsSelected ? isHover ? colIndexes : selectedColIndexes : colIndexes;
153
- return showCondition && /*#__PURE__*/React.createElement("div", {
153
+ return /*#__PURE__*/React.createElement("div", {
154
154
  key: type,
155
155
  style: {
156
156
  gridColumn: isSelecting ? selectedColumnPosition : gridColumnPosition,
@@ -162,7 +162,7 @@ export const ColumnControls = ({
162
162
  zIndex: 99
163
163
  },
164
164
  "data-column-control-index": hoveredCell.colIndex,
165
- "data-testid": 'table-floating-column-control'
165
+ "data-testid": `table-floating-column-${isSelecting ? selectedColIndexes[0] : colIndex}-drag-handle`
166
166
  }, /*#__PURE__*/React.createElement(DragHandle, {
167
167
  isDragMenuTarget: !isHover,
168
168
  direction: "column",
@@ -130,7 +130,7 @@ const DragControlsComponent = ({
130
130
  const currentSelectionAppearance = isRowsSelected ? isInDanger ? 'danger' : 'selected' : hoveredAppearance;
131
131
  const isSelecting = isRowsSelected && !isHover;
132
132
  const indexes = isRowsSelected ? isHover ? rowIndexes : selectedRowIndexes : rowIndexes;
133
- return showCondition && /*#__PURE__*/React.createElement("div", {
133
+ return /*#__PURE__*/React.createElement("div", {
134
134
  key: type,
135
135
  style: {
136
136
  gridRow: isSelecting ? selectedRowPosition : gridRowPosition,
@@ -140,7 +140,7 @@ const DragControlsComponent = ({
140
140
  position: 'relative',
141
141
  right: '-0.5px'
142
142
  },
143
- "data-testid": 'table-floating-row-drag-handle'
143
+ "data-testid": `table-floating-row-${isSelecting ? selectedRowIndexes[0] : rowIndex}-drag-handle`
144
144
  }, /*#__PURE__*/React.createElement(DragHandle, {
145
145
  isDragMenuTarget: !isHover,
146
146
  direction: "row",
@@ -1,5 +1,6 @@
1
1
  import { tableCellBorderWidth, tableMarginTop } from '@atlaskit/editor-common/styles';
2
2
  import { akEditorTableBorder, akEditorTableBorderSelected, akEditorTableCellBlanketDeleted, akEditorTableCellBlanketSelected, akEditorTableHeaderCellBackground, akEditorTableToolbar, akEditorTableToolbarSize, akEditorUnitZIndex, akRichMediaResizeZIndex } from '@atlaskit/editor-shared-styles';
3
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
3
4
  import { B200, N0, N20, N200, N20A, N300, R300, R400, R75 } from '@atlaskit/theme/colors';
4
5
  import { RESIZE_HANDLE_AREA_DECORATION_GAP } from '../types';
5
6
 
@@ -49,7 +50,7 @@ export const resizeHandlerAreaWidth = RESIZE_HANDLE_AREA_DECORATION_GAP / 3;
49
50
  export const resizeLineWidth = 2;
50
51
  export const resizeHandlerZIndex = columnControlsZIndex + akRichMediaResizeZIndex;
51
52
  export const contextualMenuTriggerSize = 16;
52
- export const contextualMenuDropdownWidth = 180;
53
+ export const contextualMenuDropdownWidth = getBooleanFF('platform.editor.table.drag-and-drop') ? 250 : 180;
53
54
  export const stickyRowZIndex = resizeHandlerZIndex + 2;
54
55
  export const stickyRowOffsetTop = 8;
55
56
  export const stickyHeaderBorderBottomWidth = 1;