@atlaskit/editor-plugin-table 24.2.3 → 24.2.4

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 (40) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/pm-plugins/commands/active-table-menu.js +14 -5
  3. package/dist/cjs/pm-plugins/drag-and-drop/plugin.js +3 -1
  4. package/dist/cjs/pm-plugins/main.js +3 -1
  5. package/dist/cjs/pm-plugins/utils/dom.js +4 -1
  6. package/dist/cjs/pm-plugins/utils/selection.js +14 -1
  7. package/dist/cjs/ui/DragHandle/index.js +36 -2
  8. package/dist/cjs/ui/FloatingInsertButton/index.js +1 -1
  9. package/dist/cjs/ui/FloatingTableMenu/index.js +4 -7
  10. package/dist/cjs/ui/TableFloatingColumnControls/ColumnControls/index.js +1 -0
  11. package/dist/cjs/ui/TableFloatingControls/RowControls/DragControls.js +1 -0
  12. package/dist/cjs/ui/event-handlers.js +14 -1
  13. package/dist/es2019/pm-plugins/commands/active-table-menu.js +14 -5
  14. package/dist/es2019/pm-plugins/drag-and-drop/plugin.js +3 -1
  15. package/dist/es2019/pm-plugins/main.js +1 -1
  16. package/dist/es2019/pm-plugins/utils/dom.js +1 -0
  17. package/dist/es2019/pm-plugins/utils/selection.js +13 -0
  18. package/dist/es2019/ui/DragHandle/index.js +37 -2
  19. package/dist/es2019/ui/FloatingInsertButton/index.js +2 -2
  20. package/dist/es2019/ui/FloatingTableMenu/index.js +4 -7
  21. package/dist/es2019/ui/TableFloatingColumnControls/ColumnControls/index.js +1 -0
  22. package/dist/es2019/ui/TableFloatingControls/RowControls/DragControls.js +1 -0
  23. package/dist/es2019/ui/event-handlers.js +15 -2
  24. package/dist/esm/pm-plugins/commands/active-table-menu.js +14 -5
  25. package/dist/esm/pm-plugins/drag-and-drop/plugin.js +3 -1
  26. package/dist/esm/pm-plugins/main.js +3 -1
  27. package/dist/esm/pm-plugins/utils/dom.js +3 -0
  28. package/dist/esm/pm-plugins/utils/selection.js +13 -0
  29. package/dist/esm/ui/DragHandle/index.js +37 -3
  30. package/dist/esm/ui/FloatingInsertButton/index.js +2 -2
  31. package/dist/esm/ui/FloatingTableMenu/index.js +4 -7
  32. package/dist/esm/ui/TableFloatingColumnControls/ColumnControls/index.js +1 -0
  33. package/dist/esm/ui/TableFloatingControls/RowControls/DragControls.js +1 -0
  34. package/dist/esm/ui/event-handlers.js +15 -2
  35. package/dist/types/pm-plugins/commands/active-table-menu.d.ts +3 -1
  36. package/dist/types/pm-plugins/utils/dom.d.ts +1 -0
  37. package/dist/types/pm-plugins/utils/selection.d.ts +8 -1
  38. package/dist/types/ui/DragHandle/index.d.ts +2 -1
  39. package/dist/types/ui/event-handlers.d.ts +1 -1
  40. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 24.2.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2a5949df6125f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2a5949df6125f) -
8
+ Under platform_editor_table_menu_updates, keep the selection toolbar suppressed after the
9
+ row/column drag menu closes while that drag-handle selection persists; any other selection
10
+ re-enables the toolbar.
11
+ - Updated dependencies
12
+
3
13
  ## 24.2.3
4
14
 
5
15
  ### Patch Changes
@@ -5,14 +5,21 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.toggleActiveTableMenu = exports.closeActiveTableMenu = void 0;
7
7
  var _pluginKey = require("../plugin-key");
8
+ var _selection = require("../utils/selection");
8
9
  var applyMenuUserIntent = function applyMenuUserIntent(tr, api, nextActiveTableMenu) {
9
- var _api$userIntent;
10
- var isRowOrColumnMenuOpen = nextActiveTableMenu.type === 'row' || nextActiveTableMenu.type === 'column';
11
- api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent(isRowOrColumnMenuOpen ? 'tableDragMenuPopupOpen' : 'default')({
10
+ var _api$userIntent2;
11
+ if (nextActiveTableMenu.type === 'row' || nextActiveTableMenu.type === 'column') {
12
+ var _api$userIntent;
13
+ api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('tableDragMenuPopupOpen')({
14
+ tr: tr
15
+ });
16
+ return;
17
+ }
18
+ api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent((0, _selection.isFullRowOrColumnSelected)(tr.selection) ? 'dragHandleSelected' : 'default')({
12
19
  tr: tr
13
20
  });
14
21
  };
15
- var closeActiveTableMenu = exports.closeActiveTableMenu = function closeActiveTableMenu(api) {
22
+ var closeActiveTableMenu = exports.closeActiveTableMenu = function closeActiveTableMenu(api, options) {
16
23
  return function (_ref) {
17
24
  var tr = _ref.tr;
18
25
  var nextActiveTableMenu = {
@@ -24,7 +31,9 @@ var closeActiveTableMenu = exports.closeActiveTableMenu = function closeActiveTa
24
31
  activeTableMenu: nextActiveTableMenu
25
32
  }
26
33
  });
27
- applyMenuUserIntent(tr, api, nextActiveTableMenu);
34
+ if (!(options !== null && options !== void 0 && options.skipUserIntent)) {
35
+ applyMenuUserIntent(tr, api, nextActiveTableMenu);
36
+ }
28
37
  if (!tr.docChanged) {
29
38
  tr.setMeta('addToHistory', false);
30
39
  }
@@ -96,7 +96,9 @@ var destroyFn = function destroyFn(editorView, editorAnalyticsAPI, isTableScalin
96
96
  api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
97
97
  var _api$userIntent;
98
98
  var tr = _ref7.tr;
99
- (0, _activeTableMenu.closeActiveTableMenu)(api)({
99
+ (0, _activeTableMenu.closeActiveTableMenu)(api, {
100
+ skipUserIntent: true
101
+ })({
100
102
  tr: tr
101
103
  });
102
104
  api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('dragging')({
@@ -348,7 +348,9 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatchAnalytic
348
348
  handleDOMEvents: {
349
349
  focus: _eventHandlers.handleFocus,
350
350
  blur: _eventHandlers.handleBlur,
351
- mousedown: (0, _eventHandlers.withCellTracking)(_eventHandlers.handleMouseDown),
351
+ mousedown: (0, _eventHandlers.withCellTracking)(function (view, event) {
352
+ return (0, _eventHandlers.handleMouseDown)(view, event, pluginInjectionApi);
353
+ }),
352
354
  mouseleave: _eventHandlers.handleMouseLeave,
353
355
  mousemove: (0, _eventHandlers.whenTableInFocus)((0, _eventHandlers.handleMouseMove)(nodeViewPortalProviderAPI), pluginInjectionApi),
354
356
  mouseenter: _eventHandlers.handleMouseEnter,
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isTableControlsButton = exports.isTableContainerOrWrapper = exports.isRowControlsButton = exports.isResizeHandleDecoration = exports.isInsertRowButton = exports.isDragRowFloatingInsertDot = exports.isDragCornerButton = exports.isDragColumnFloatingInsertDot = exports.isCornerButton = exports.isColumnControlsDecorations = exports.isCell = exports.hasResizeHandler = exports.getTree = exports.getTop = exports.getMousePositionVerticalRelativeByElement = exports.getMousePositionHorizontalRelativeByElement = exports.getIndexAttributeSourceElement = exports.getColumnOrRowIndex = exports.findNearestCellIndexToPoint = exports.areAllRectsZero = void 0;
6
+ exports.isTableDragHandleButton = exports.isTableControlsButton = exports.isTableContainerOrWrapper = exports.isRowControlsButton = exports.isResizeHandleDecoration = exports.isInsertRowButton = exports.isDragRowFloatingInsertDot = exports.isDragCornerButton = exports.isDragColumnFloatingInsertDot = exports.isCornerButton = exports.isColumnControlsDecorations = exports.isCell = exports.hasResizeHandler = exports.getTree = exports.getTop = exports.getMousePositionVerticalRelativeByElement = exports.getMousePositionHorizontalRelativeByElement = exports.getIndexAttributeSourceElement = exports.getColumnOrRowIndex = exports.findNearestCellIndexToPoint = exports.areAllRectsZero = void 0;
7
7
  var _utils = require("@atlaskit/editor-common/utils");
8
8
  var _types = require("../../types");
9
9
  var isCell = exports.isCell = function isCell(node) {
@@ -63,6 +63,9 @@ var isDragColumnFloatingInsertDot = exports.isDragColumnFloatingInsertDot = func
63
63
  var isDragCornerButton = exports.isDragCornerButton = function isDragCornerButton(node) {
64
64
  return (0, _utils.containsClassName)(node, _types.TableCssClassName.DRAG_CORNER_BUTTON) || (0, _utils.containsClassName)(node, _types.TableCssClassName.DRAG_CORNER_BUTTON_INNER);
65
65
  };
66
+ var isTableDragHandleButton = exports.isTableDragHandleButton = function isTableDragHandleButton(target) {
67
+ return target instanceof HTMLElement && Boolean(target.closest(".".concat(_types.TableCssClassName.DRAG_HANDLE_BUTTON_CONTAINER)));
68
+ };
66
69
 
67
70
  /*
68
71
  * This function returns which side of a given element the mouse cursor is,
@@ -3,7 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isRowSelectionWithMergedFirstColumn = exports.isColumnSelectionWithMergedFirstRow = exports.getSelectedRowIndexes = exports.getSelectedColumnIndexes = void 0;
6
+ exports.isRowSelectionWithMergedFirstColumn = exports.isFullRowOrColumnSelected = exports.isColumnSelectionWithMergedFirstRow = exports.getSelectedRowIndexes = exports.getSelectedColumnIndexes = void 0;
7
+ var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
7
8
  var _tableMap = require("@atlaskit/editor-tables/table-map");
8
9
  var _utils = require("@atlaskit/editor-tables/utils");
9
10
  var getSelectedColumnIndexes = exports.getSelectedColumnIndexes = function getSelectedColumnIndexes(selectionRect) {
@@ -77,4 +78,16 @@ var isRowSelectionWithMergedFirstColumn = exports.isRowSelectionWithMergedFirstC
77
78
  }
78
79
  }
79
80
  return true;
81
+ };
82
+
83
+ /**
84
+ * Returns `true` when the selection covers one or more complete rows or columns (the kind of
85
+ * selection produced by clicking a row/column drag handle), including the merged-cell variants
86
+ * where `CellSelection.isRowSelection()` / `isColSelection()` return `false`.
87
+ */
88
+ var isFullRowOrColumnSelected = exports.isFullRowOrColumnSelected = function isFullRowOrColumnSelected(selection) {
89
+ if (!(selection instanceof _cellSelection.CellSelection)) {
90
+ return false;
91
+ }
92
+ return selection.isRowSelection() || selection.isColSelection() || isRowSelectionWithMergedFirstColumn(selection) || isColumnSelectionWithMergedFirstRow(selection);
80
93
  };
@@ -19,6 +19,7 @@ var _editorTables = require("@atlaskit/editor-tables");
19
19
  var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
20
20
  var _setCustomNativeDragPreview = require("@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview");
21
21
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
22
+ var _activeTableMenu = require("../../pm-plugins/commands/active-table-menu");
22
23
  var _pluginFactory = require("../../pm-plugins/drag-and-drop/plugin-factory");
23
24
  var _mergedCells = require("../../pm-plugins/utils/merged-cells");
24
25
  var _types = require("../../types");
@@ -29,7 +30,8 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
29
30
  /* eslint-disable @atlaskit/design-system/no-html-button */
30
31
 
31
32
  var DragHandleComponent = function DragHandleComponent(_ref) {
32
- var isDragMenuTarget = _ref.isDragMenuTarget,
33
+ var api = _ref.api,
34
+ isDragMenuTarget = _ref.isDragMenuTarget,
33
35
  tableLocalId = _ref.tableLocalId,
34
36
  _ref$direction = _ref.direction,
35
37
  direction = _ref$direction === void 0 ? 'row' : _ref$direction,
@@ -160,6 +162,35 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
160
162
  }, [tableLocalId, direction, indexes, isRow, editorView.state.selection, hasMergedCells]);
161
163
  var showDragMenuAnchorId = isRow ? 'drag-handle-button-row' : 'drag-handle-button-column';
162
164
  var browser = (0, _browser.getBrowserInfo)();
165
+
166
+ // Clicking the drag handle's clickable zone is a plain row/column selection (not the menu
167
+ // trigger), so the selection toolbar should appear. The floating menu defers closing for clicks
168
+ // inside the drag controls, so we close it here and reset the user intent to 'default' (in the
169
+ // same transaction) so the toolbar is shown.
170
+ var closeActiveDragMenuAndShowToolbar = (0, _react.useCallback)(function () {
171
+ var _api$table, _api$core;
172
+ if (!api) {
173
+ return;
174
+ }
175
+ var activeTableMenu = (_api$table = api.table) === null || _api$table === void 0 || (_api$table = _api$table.sharedState.currentState()) === null || _api$table === void 0 ? void 0 : _api$table.activeTableMenu;
176
+ var isActiveTableMenuOpen = (activeTableMenu === null || activeTableMenu === void 0 ? void 0 : activeTableMenu.type) === 'row' || (activeTableMenu === null || activeTableMenu === void 0 ? void 0 : activeTableMenu.type) === 'column';
177
+ if (!isActiveTableMenuOpen) {
178
+ return;
179
+ }
180
+ (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref5) {
181
+ var _api$userIntent;
182
+ var tr = _ref5.tr;
183
+ (0, _activeTableMenu.closeActiveTableMenu)(api, {
184
+ skipUserIntent: true
185
+ })({
186
+ tr: tr
187
+ });
188
+ (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('default')({
189
+ tr: tr
190
+ });
191
+ return tr;
192
+ });
193
+ }, [api]);
163
194
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("button", {
164
195
  type: "button"
165
196
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -185,7 +216,10 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
185
216
  // return focus to editor so copying table selections whilst still works, i cannot call e.preventDefault in a mousemove event as this stops dragstart events from firing
186
217
  // -> this is bad for a11y but is the current standard new copy/paste keyboard shortcuts should be introduced instead
187
218
  editorView.focus();
188
- if (isDragMenuOpen) {
219
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_menu_updates', 'isEnabled', true)) {
220
+ // New menu: close the open row/column menu (and show the selection toolbar).
221
+ closeActiveDragMenuAndShowToolbar();
222
+ } else if (isDragMenuOpen) {
189
223
  toggleDragMenu && toggleDragMenu('mouse', e);
190
224
  }
191
225
  },
@@ -82,7 +82,7 @@ var FloatingInsertButton = exports.FloatingInsertButton = /*#__PURE__*/function
82
82
  }
83
83
  var tr = editorView.state.tr;
84
84
  if ((0, _expValEquals.expValEquals)('platform_editor_table_menu_updates', 'isEnabled', true)) {
85
- if (tr.selection instanceof _cellSelection.CellSelection && (tr.selection.isColSelection() || tr.selection.isRowSelection() || (0, _selection.isColumnSelectionWithMergedFirstRow)(tr.selection) || (0, _selection.isRowSelectionWithMergedFirstColumn)(tr.selection))) {
85
+ if ((0, _selection.isFullRowOrColumnSelected)(tr.selection)) {
86
86
  return null;
87
87
  }
88
88
  } else {
@@ -64,9 +64,6 @@ var FloatingTableMenu = function FloatingTableMenu(_ref) {
64
64
  popupContentRef.current = el;
65
65
  setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 || setOutsideClickTargetRef(el);
66
66
  }, [setOutsideClickTargetRef]);
67
- var dismiss = (0, _react.useCallback)(function () {
68
- api === null || api === void 0 || api.core.actions.execute((0, _commands.closeActiveTableMenu)(api));
69
- }, [api]);
70
67
  var returnFocusToDragHandle = (0, _react.useCallback)(function () {
71
68
  // Match legacy DragMenu's closeMenu('handle') behaviour.
72
69
  var handleId = dragMenuDirection === 'row' ? '#drag-handle-button-row' : '#drag-handle-button-column';
@@ -99,9 +96,9 @@ var FloatingTableMenu = function FloatingTableMenu(_ref) {
99
96
  var handleEscape = (0, _react.useCallback)(function (event) {
100
97
  event.preventDefault();
101
98
  event.stopPropagation();
102
- dismiss();
99
+ api === null || api === void 0 || api.core.actions.execute((0, _commands.closeActiveTableMenu)(api));
103
100
  returnFocusToDragHandle();
104
- }, [dismiss, returnFocusToDragHandle]);
101
+ }, [api, returnFocusToDragHandle]);
105
102
 
106
103
  // Memoize the editor DOM reference so the provider doesn't re-bind listeners
107
104
  // on every render (the provider depends on `dom` in its effect's deps).
@@ -122,8 +119,8 @@ var FloatingTableMenu = function FloatingTableMenu(_ref) {
122
119
  if (target instanceof Node && (_popupContentRef$curr = popupContentRef.current) !== null && _popupContentRef$curr !== void 0 && _popupContentRef$curr.contains(target) || target instanceof Element && (target.closest(DRAG_HANDLE_CONTROLS_SELECTOR) || target.closest(NESTED_DROPDOWN_SELECTOR))) {
123
120
  return;
124
121
  }
125
- dismiss();
126
- }, [dismiss]);
122
+ api === null || api === void 0 || api.core.actions.execute((0, _commands.closeActiveTableMenu)(api));
123
+ }, [api]);
127
124
  if (!isDragMenuOpen || !targetCellPosition || editorView.state.doc.nodeSize <= targetCellPosition) {
128
125
  return null;
129
126
  }
@@ -233,6 +233,7 @@ var ColumnControls = exports.ColumnControls = function ColumnControls(_ref) {
233
233
  },
234
234
  "data-testid": "table-floating-column-".concat(isHover ? colIndex : isPlaceholder ? appearance : selectedColIndexes[0], "-drag-handle")
235
235
  }, /*#__PURE__*/_react.default.createElement(_DragHandle.DragHandle, {
236
+ api: api,
236
237
  isDragMenuTarget: !isHover,
237
238
  direction: "column",
238
239
  tableLocalId: localId || '',
@@ -224,6 +224,7 @@ var DragControls = exports.DragControls = function DragControls(_ref) {
224
224
  "data-selected-row-index": selectedRowIndexes[0],
225
225
  "data-handle-appearance": appearance
226
226
  }, /*#__PURE__*/_react.default.createElement(_DragHandle.DragHandle, {
227
+ api: api,
227
228
  isDragMenuTarget: !isHover,
228
229
  direction: "row",
229
230
  tableLocalId: currentNodeLocalId,
@@ -207,14 +207,27 @@ var handleMouseUp = exports.handleMouseUp = function handleMouseUp(view, mouseEv
207
207
  }
208
208
  return false;
209
209
  };
210
+ var resetDragHandleSelectedIntentOnMouseDown = function resetDragHandleSelectedIntentOnMouseDown(event, api) {
211
+ var _api$userIntent;
212
+ if ((0, _dom.isTableDragHandleButton)(event.target)) {
213
+ return;
214
+ }
215
+ if ((api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent) === 'dragHandleSelected') {
216
+ var _api$core, _api$userIntent2;
217
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default'));
218
+ }
219
+ };
210
220
 
211
221
  // Ignore any `mousedown` `event` from control and numbered column buttons
212
222
  // PM end up changing selection during shift selection if not prevented
213
- var handleMouseDown = exports.handleMouseDown = function handleMouseDown(_, event) {
223
+ var handleMouseDown = exports.handleMouseDown = function handleMouseDown(_view, event, api) {
214
224
  var isControl = !!(event.target && event.target instanceof HTMLElement && ((0, _dom.isTableContainerOrWrapper)(event.target) || (0, _dom.isColumnControlsDecorations)(event.target) || (0, _dom.isRowControlsButton)(event.target) || (0, _dom.isDragCornerButton)(event.target)));
215
225
  if (isControl) {
216
226
  event.preventDefault();
217
227
  }
228
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_menu_updates', 'isEnabled', true)) {
229
+ resetDragHandleSelectedIntentOnMouseDown(event, api);
230
+ }
218
231
  return isControl;
219
232
  };
220
233
  var handleMouseOut = exports.handleMouseOut = function handleMouseOut(view, mouseEvent) {
@@ -1,12 +1,19 @@
1
1
  import { pluginKey } from '../plugin-key';
2
+ import { isFullRowOrColumnSelected } from '../utils/selection';
2
3
  const applyMenuUserIntent = (tr, api, nextActiveTableMenu) => {
3
- var _api$userIntent;
4
- const isRowOrColumnMenuOpen = nextActiveTableMenu.type === 'row' || nextActiveTableMenu.type === 'column';
5
- api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent(isRowOrColumnMenuOpen ? 'tableDragMenuPopupOpen' : 'default')({
4
+ var _api$userIntent2;
5
+ if (nextActiveTableMenu.type === 'row' || nextActiveTableMenu.type === 'column') {
6
+ var _api$userIntent;
7
+ api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('tableDragMenuPopupOpen')({
8
+ tr
9
+ });
10
+ return;
11
+ }
12
+ api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent(isFullRowOrColumnSelected(tr.selection) ? 'dragHandleSelected' : 'default')({
6
13
  tr
7
14
  });
8
15
  };
9
- export const closeActiveTableMenu = api => ({
16
+ export const closeActiveTableMenu = (api, options) => ({
10
17
  tr
11
18
  }) => {
12
19
  const nextActiveTableMenu = {
@@ -18,7 +25,9 @@ export const closeActiveTableMenu = api => ({
18
25
  activeTableMenu: nextActiveTableMenu
19
26
  }
20
27
  });
21
- applyMenuUserIntent(tr, api, nextActiveTableMenu);
28
+ if (!(options !== null && options !== void 0 && options.skipUserIntent)) {
29
+ applyMenuUserIntent(tr, api, nextActiveTableMenu);
30
+ }
22
31
  if (!tr.docChanged) {
23
32
  tr.setMeta('addToHistory', false);
24
33
  }
@@ -98,7 +98,9 @@ const destroyFn = (editorView, editorAnalyticsAPI, isTableScalingEnabled, isTabl
98
98
  tr
99
99
  }) => {
100
100
  var _api$userIntent;
101
- closeActiveTableMenu(api)({
101
+ closeActiveTableMenu(api, {
102
+ skipUserIntent: true
103
+ })({
102
104
  tr
103
105
  });
104
106
  api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('dragging')({
@@ -346,7 +346,7 @@ export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI
346
346
  handleDOMEvents: {
347
347
  focus: handleFocus,
348
348
  blur: handleBlur,
349
- mousedown: withCellTracking(handleMouseDown),
349
+ mousedown: withCellTracking((view, event) => handleMouseDown(view, event, pluginInjectionApi)),
350
350
  mouseleave: handleMouseLeave,
351
351
  mousemove: whenTableInFocus(handleMouseMove(nodeViewPortalProviderAPI), pluginInjectionApi),
352
352
  mouseenter: handleMouseEnter,
@@ -35,6 +35,7 @@ export const isTableContainerOrWrapper = node => containsClassName(node, ClassNa
35
35
  export const isDragRowFloatingInsertDot = node => containsClassName(node, ClassName.DRAG_ROW_FLOATING_INSERT_DOT_WRAPPER);
36
36
  export const isDragColumnFloatingInsertDot = node => containsClassName(node, ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT_WRAPPER);
37
37
  export const isDragCornerButton = node => containsClassName(node, ClassName.DRAG_CORNER_BUTTON) || containsClassName(node, ClassName.DRAG_CORNER_BUTTON_INNER);
38
+ export const isTableDragHandleButton = target => target instanceof HTMLElement && Boolean(target.closest(`.${ClassName.DRAG_HANDLE_BUTTON_CONTAINER}`));
38
39
 
39
40
  /*
40
41
  * This function returns which side of a given element the mouse cursor is,
@@ -1,3 +1,4 @@
1
+ import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
1
2
  import { TableMap } from '@atlaskit/editor-tables/table-map';
2
3
  import { findTableClosestToPos, getSelectionRect } from '@atlaskit/editor-tables/utils';
3
4
  export const getSelectedColumnIndexes = selectionRect => {
@@ -71,4 +72,16 @@ export const isRowSelectionWithMergedFirstColumn = selection => {
71
72
  }
72
73
  }
73
74
  return true;
75
+ };
76
+
77
+ /**
78
+ * Returns `true` when the selection covers one or more complete rows or columns (the kind of
79
+ * selection produced by clicking a row/column drag handle), including the merged-cell variants
80
+ * where `CellSelection.isRowSelection()` / `isColSelection()` return `false`.
81
+ */
82
+ export const isFullRowOrColumnSelected = selection => {
83
+ if (!(selection instanceof CellSelection)) {
84
+ return false;
85
+ }
86
+ return selection.isRowSelection() || selection.isColSelection() || isRowSelectionWithMergedFirstColumn(selection) || isColumnSelectionWithMergedFirstRow(selection);
74
87
  };
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @atlaskit/design-system/no-html-button */
2
2
 
3
- import React, { useEffect, useMemo, useRef, useState } from 'react';
3
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import classnames from 'classnames';
5
5
  import ReactDOM from 'react-dom';
6
6
  import { injectIntl } from 'react-intl';
@@ -11,6 +11,7 @@ import { findTable, TableMap } from '@atlaskit/editor-tables';
11
11
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
12
12
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
13
13
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
14
+ import { closeActiveTableMenu } from '../../pm-plugins/commands/active-table-menu';
14
15
  import { getPluginState as getDnDPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
15
16
  import { findDuplicatePosition, hasMergedCellsInSelection } from '../../pm-plugins/utils/merged-cells';
16
17
  import { TableCssClassName as ClassName } from '../../types';
@@ -18,6 +19,7 @@ import { dragTableInsertColumnButtonSize } from '../consts';
18
19
  import { DragPreview } from '../DragPreview';
19
20
  import { HandleIconComponent } from './HandleIconComponent';
20
21
  const DragHandleComponent = ({
22
+ api,
21
23
  isDragMenuTarget,
22
24
  tableLocalId,
23
25
  direction = 'row',
@@ -148,6 +150,36 @@ const DragHandleComponent = ({
148
150
  }, [tableLocalId, direction, indexes, isRow, editorView.state.selection, hasMergedCells]);
149
151
  const showDragMenuAnchorId = isRow ? 'drag-handle-button-row' : 'drag-handle-button-column';
150
152
  const browser = getBrowserInfo();
153
+
154
+ // Clicking the drag handle's clickable zone is a plain row/column selection (not the menu
155
+ // trigger), so the selection toolbar should appear. The floating menu defers closing for clicks
156
+ // inside the drag controls, so we close it here and reset the user intent to 'default' (in the
157
+ // same transaction) so the toolbar is shown.
158
+ const closeActiveDragMenuAndShowToolbar = useCallback(() => {
159
+ var _api$table, _api$table$sharedStat, _api$core;
160
+ if (!api) {
161
+ return;
162
+ }
163
+ const activeTableMenu = (_api$table = api.table) === null || _api$table === void 0 ? void 0 : (_api$table$sharedStat = _api$table.sharedState.currentState()) === null || _api$table$sharedStat === void 0 ? void 0 : _api$table$sharedStat.activeTableMenu;
164
+ const isActiveTableMenuOpen = (activeTableMenu === null || activeTableMenu === void 0 ? void 0 : activeTableMenu.type) === 'row' || (activeTableMenu === null || activeTableMenu === void 0 ? void 0 : activeTableMenu.type) === 'column';
165
+ if (!isActiveTableMenuOpen) {
166
+ return;
167
+ }
168
+ (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
169
+ tr
170
+ }) => {
171
+ var _api$userIntent;
172
+ closeActiveTableMenu(api, {
173
+ skipUserIntent: true
174
+ })({
175
+ tr
176
+ });
177
+ (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('default')({
178
+ tr
179
+ });
180
+ return tr;
181
+ });
182
+ }, [api]);
151
183
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
152
184
  type: "button"
153
185
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -175,7 +207,10 @@ const DragHandleComponent = ({
175
207
  // return focus to editor so copying table selections whilst still works, i cannot call e.preventDefault in a mousemove event as this stops dragstart events from firing
176
208
  // -> this is bad for a11y but is the current standard new copy/paste keyboard shortcuts should be introduced instead
177
209
  editorView.focus();
178
- if (isDragMenuOpen) {
210
+ if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
211
+ // New menu: close the open row/column menu (and show the selection toolbar).
212
+ closeActiveDragMenuAndShowToolbar();
213
+ } else if (isDragMenuOpen) {
179
214
  toggleDragMenu && toggleDragMenu('mouse', e);
180
215
  }
181
216
  },
@@ -13,7 +13,7 @@ import { findTable } from '@atlaskit/editor-tables/utils';
13
13
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
14
14
  import { insertColumnWithAnalytics, insertRowWithAnalytics } from '../../pm-plugins/commands/commands-with-analytics';
15
15
  import { checkIfNumberColumnEnabled } from '../../pm-plugins/utils/nodes';
16
- import { isColumnSelectionWithMergedFirstRow, isRowSelectionWithMergedFirstColumn } from '../../pm-plugins/utils/selection';
16
+ import { isFullRowOrColumnSelected } from '../../pm-plugins/utils/selection';
17
17
  import { TableCssClassName as ClassName } from '../../types';
18
18
  import getPopupOptions from './getPopupOptions';
19
19
  import { DragAndDropInsertButton } from './InsertButton';
@@ -67,7 +67,7 @@ export class FloatingInsertButton extends React.Component {
67
67
  }
68
68
  } = editorView;
69
69
  if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
70
- if (tr.selection instanceof CellSelection && (tr.selection.isColSelection() || tr.selection.isRowSelection() || isColumnSelectionWithMergedFirstRow(tr.selection) || isRowSelectionWithMergedFirstColumn(tr.selection))) {
70
+ if (isFullRowOrColumnSelected(tr.selection)) {
71
71
  return null;
72
72
  }
73
73
  } else {
@@ -58,9 +58,6 @@ const FloatingTableMenu = ({
58
58
  popupContentRef.current = el;
59
59
  setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 ? void 0 : setOutsideClickTargetRef(el);
60
60
  }, [setOutsideClickTargetRef]);
61
- const dismiss = useCallback(() => {
62
- api === null || api === void 0 ? void 0 : api.core.actions.execute(closeActiveTableMenu(api));
63
- }, [api]);
64
61
  const returnFocusToDragHandle = useCallback(() => {
65
62
  // Match legacy DragMenu's closeMenu('handle') behaviour.
66
63
  const handleId = dragMenuDirection === 'row' ? '#drag-handle-button-row' : '#drag-handle-button-column';
@@ -93,9 +90,9 @@ const FloatingTableMenu = ({
93
90
  const handleEscape = useCallback(event => {
94
91
  event.preventDefault();
95
92
  event.stopPropagation();
96
- dismiss();
93
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(closeActiveTableMenu(api));
97
94
  returnFocusToDragHandle();
98
- }, [dismiss, returnFocusToDragHandle]);
95
+ }, [api, returnFocusToDragHandle]);
99
96
 
100
97
  // Memoize the editor DOM reference so the provider doesn't re-bind listeners
101
98
  // on every render (the provider depends on `dom` in its effect's deps).
@@ -112,8 +109,8 @@ const FloatingTableMenu = ({
112
109
  if (target instanceof Node && (_popupContentRef$curr = popupContentRef.current) !== null && _popupContentRef$curr !== void 0 && _popupContentRef$curr.contains(target) || target instanceof Element && (target.closest(DRAG_HANDLE_CONTROLS_SELECTOR) || target.closest(NESTED_DROPDOWN_SELECTOR))) {
113
110
  return;
114
111
  }
115
- dismiss();
116
- }, [dismiss]);
112
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(closeActiveTableMenu(api));
113
+ }, [api]);
117
114
  if (!isDragMenuOpen || !targetCellPosition || editorView.state.doc.nodeSize <= targetCellPosition) {
118
115
  return null;
119
116
  }
@@ -232,6 +232,7 @@ export const ColumnControls = ({
232
232
  },
233
233
  "data-testid": `table-floating-column-${isHover ? colIndex : isPlaceholder ? appearance : selectedColIndexes[0]}-drag-handle`
234
234
  }, /*#__PURE__*/React.createElement(DragHandle, {
235
+ api: api,
235
236
  isDragMenuTarget: !isHover,
236
237
  direction: "column",
237
238
  tableLocalId: localId || '',
@@ -215,6 +215,7 @@ export const DragControls = ({
215
215
  "data-selected-row-index": selectedRowIndexes[0],
216
216
  "data-handle-appearance": appearance
217
217
  }, /*#__PURE__*/React.createElement(DragHandle, {
218
+ api: api,
218
219
  isDragMenuTarget: !isHover,
219
220
  direction: "row",
220
221
  tableLocalId: currentNodeLocalId,
@@ -17,7 +17,7 @@ import { deleteColumns } from '../pm-plugins/transforms/delete-columns';
17
17
  import { deleteRows } from '../pm-plugins/transforms/delete-rows';
18
18
  import { getSelectedCellInfo } from '../pm-plugins/utils/analytics';
19
19
  import { convertHTMLCellIndexToColumnIndex, getColumnIndexByMousePosition, getColumnIndexMappedToColumnIndexInFirstRow } from '../pm-plugins/utils/column-controls';
20
- import { getColumnOrRowIndex, getIndexAttributeSourceElement, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from '../pm-plugins/utils/dom';
20
+ import { getColumnOrRowIndex, getIndexAttributeSourceElement, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton, isTableDragHandleButton } from '../pm-plugins/utils/dom';
21
21
  import { getAllowAddColumnCustomStep } from '../pm-plugins/utils/get-allow-add-column-custom-step';
22
22
  import { getRowIndexByMousePosition } from '../pm-plugins/utils/row-controls';
23
23
  import { TableCssClassName as ClassName, RESIZE_HANDLE_AREA_DECORATION_GAP } from '../types';
@@ -197,14 +197,27 @@ export const handleMouseUp = (view, mouseEvent) => {
197
197
  }
198
198
  return false;
199
199
  };
200
+ const resetDragHandleSelectedIntentOnMouseDown = (event, api) => {
201
+ var _api$userIntent, _api$userIntent$share;
202
+ if (isTableDragHandleButton(event.target)) {
203
+ return;
204
+ }
205
+ if ((api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : (_api$userIntent$share = _api$userIntent.sharedState.currentState()) === null || _api$userIntent$share === void 0 ? void 0 : _api$userIntent$share.currentUserIntent) === 'dragHandleSelected') {
206
+ var _api$core, _api$userIntent2;
207
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default'));
208
+ }
209
+ };
200
210
 
201
211
  // Ignore any `mousedown` `event` from control and numbered column buttons
202
212
  // PM end up changing selection during shift selection if not prevented
203
- export const handleMouseDown = (_, event) => {
213
+ export const handleMouseDown = (_view, event, api) => {
204
214
  const isControl = !!(event.target && event.target instanceof HTMLElement && (isTableContainerOrWrapper(event.target) || isColumnControlsDecorations(event.target) || isRowControlsButton(event.target) || isDragCornerButton(event.target)));
205
215
  if (isControl) {
206
216
  event.preventDefault();
207
217
  }
218
+ if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
219
+ resetDragHandleSelectedIntentOnMouseDown(event, api);
220
+ }
208
221
  return isControl;
209
222
  };
210
223
  export const handleMouseOut = (view, mouseEvent) => {
@@ -1,12 +1,19 @@
1
1
  import { pluginKey } from '../plugin-key';
2
+ import { isFullRowOrColumnSelected } from '../utils/selection';
2
3
  var applyMenuUserIntent = function applyMenuUserIntent(tr, api, nextActiveTableMenu) {
3
- var _api$userIntent;
4
- var isRowOrColumnMenuOpen = nextActiveTableMenu.type === 'row' || nextActiveTableMenu.type === 'column';
5
- api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent(isRowOrColumnMenuOpen ? 'tableDragMenuPopupOpen' : 'default')({
4
+ var _api$userIntent2;
5
+ if (nextActiveTableMenu.type === 'row' || nextActiveTableMenu.type === 'column') {
6
+ var _api$userIntent;
7
+ api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('tableDragMenuPopupOpen')({
8
+ tr: tr
9
+ });
10
+ return;
11
+ }
12
+ api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent(isFullRowOrColumnSelected(tr.selection) ? 'dragHandleSelected' : 'default')({
6
13
  tr: tr
7
14
  });
8
15
  };
9
- export var closeActiveTableMenu = function closeActiveTableMenu(api) {
16
+ export var closeActiveTableMenu = function closeActiveTableMenu(api, options) {
10
17
  return function (_ref) {
11
18
  var tr = _ref.tr;
12
19
  var nextActiveTableMenu = {
@@ -18,7 +25,9 @@ export var closeActiveTableMenu = function closeActiveTableMenu(api) {
18
25
  activeTableMenu: nextActiveTableMenu
19
26
  }
20
27
  });
21
- applyMenuUserIntent(tr, api, nextActiveTableMenu);
28
+ if (!(options !== null && options !== void 0 && options.skipUserIntent)) {
29
+ applyMenuUserIntent(tr, api, nextActiveTableMenu);
30
+ }
22
31
  if (!tr.docChanged) {
23
32
  tr.setMeta('addToHistory', false);
24
33
  }
@@ -90,7 +90,9 @@ var destroyFn = function destroyFn(editorView, editorAnalyticsAPI, isTableScalin
90
90
  api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
91
91
  var _api$userIntent;
92
92
  var tr = _ref7.tr;
93
- closeActiveTableMenu(api)({
93
+ closeActiveTableMenu(api, {
94
+ skipUserIntent: true
95
+ })({
94
96
  tr: tr
95
97
  });
96
98
  api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('dragging')({
@@ -341,7 +341,9 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
341
341
  handleDOMEvents: {
342
342
  focus: handleFocus,
343
343
  blur: handleBlur,
344
- mousedown: withCellTracking(handleMouseDown),
344
+ mousedown: withCellTracking(function (view, event) {
345
+ return handleMouseDown(view, event, pluginInjectionApi);
346
+ }),
345
347
  mouseleave: handleMouseLeave,
346
348
  mousemove: whenTableInFocus(handleMouseMove(nodeViewPortalProviderAPI), pluginInjectionApi),
347
349
  mouseenter: handleMouseEnter,
@@ -57,6 +57,9 @@ export var isDragColumnFloatingInsertDot = function isDragColumnFloatingInsertDo
57
57
  export var isDragCornerButton = function isDragCornerButton(node) {
58
58
  return containsClassName(node, ClassName.DRAG_CORNER_BUTTON) || containsClassName(node, ClassName.DRAG_CORNER_BUTTON_INNER);
59
59
  };
60
+ export var isTableDragHandleButton = function isTableDragHandleButton(target) {
61
+ return target instanceof HTMLElement && Boolean(target.closest(".".concat(ClassName.DRAG_HANDLE_BUTTON_CONTAINER)));
62
+ };
60
63
 
61
64
  /*
62
65
  * This function returns which side of a given element the mouse cursor is,
@@ -1,3 +1,4 @@
1
+ import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
1
2
  import { TableMap } from '@atlaskit/editor-tables/table-map';
2
3
  import { findTableClosestToPos, getSelectionRect } from '@atlaskit/editor-tables/utils';
3
4
  export var getSelectedColumnIndexes = function getSelectedColumnIndexes(selectionRect) {
@@ -71,4 +72,16 @@ export var isRowSelectionWithMergedFirstColumn = function isRowSelectionWithMerg
71
72
  }
72
73
  }
73
74
  return true;
75
+ };
76
+
77
+ /**
78
+ * Returns `true` when the selection covers one or more complete rows or columns (the kind of
79
+ * selection produced by clicking a row/column drag handle), including the merged-cell variants
80
+ * where `CellSelection.isRowSelection()` / `isColSelection()` return `false`.
81
+ */
82
+ export var isFullRowOrColumnSelected = function isFullRowOrColumnSelected(selection) {
83
+ if (!(selection instanceof CellSelection)) {
84
+ return false;
85
+ }
86
+ return selection.isRowSelection() || selection.isColSelection() || isRowSelectionWithMergedFirstColumn(selection) || isColumnSelectionWithMergedFirstRow(selection);
74
87
  };
@@ -2,7 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  /* eslint-disable @atlaskit/design-system/no-html-button */
4
4
 
5
- import React, { useEffect, useMemo, useRef, useState } from 'react';
5
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
6
  import classnames from 'classnames';
7
7
  import ReactDOM from 'react-dom';
8
8
  import { injectIntl } from 'react-intl';
@@ -13,6 +13,7 @@ import { findTable, TableMap } from '@atlaskit/editor-tables';
13
13
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
14
14
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
15
15
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
16
+ import { closeActiveTableMenu } from '../../pm-plugins/commands/active-table-menu';
16
17
  import { getPluginState as getDnDPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
17
18
  import { findDuplicatePosition, hasMergedCellsInSelection } from '../../pm-plugins/utils/merged-cells';
18
19
  import { TableCssClassName as ClassName } from '../../types';
@@ -20,7 +21,8 @@ import { dragTableInsertColumnButtonSize } from '../consts';
20
21
  import { DragPreview } from '../DragPreview';
21
22
  import { HandleIconComponent } from './HandleIconComponent';
22
23
  var DragHandleComponent = function DragHandleComponent(_ref) {
23
- var isDragMenuTarget = _ref.isDragMenuTarget,
24
+ var api = _ref.api,
25
+ isDragMenuTarget = _ref.isDragMenuTarget,
24
26
  tableLocalId = _ref.tableLocalId,
25
27
  _ref$direction = _ref.direction,
26
28
  direction = _ref$direction === void 0 ? 'row' : _ref$direction,
@@ -151,6 +153,35 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
151
153
  }, [tableLocalId, direction, indexes, isRow, editorView.state.selection, hasMergedCells]);
152
154
  var showDragMenuAnchorId = isRow ? 'drag-handle-button-row' : 'drag-handle-button-column';
153
155
  var browser = getBrowserInfo();
156
+
157
+ // Clicking the drag handle's clickable zone is a plain row/column selection (not the menu
158
+ // trigger), so the selection toolbar should appear. The floating menu defers closing for clicks
159
+ // inside the drag controls, so we close it here and reset the user intent to 'default' (in the
160
+ // same transaction) so the toolbar is shown.
161
+ var closeActiveDragMenuAndShowToolbar = useCallback(function () {
162
+ var _api$table, _api$core;
163
+ if (!api) {
164
+ return;
165
+ }
166
+ var activeTableMenu = (_api$table = api.table) === null || _api$table === void 0 || (_api$table = _api$table.sharedState.currentState()) === null || _api$table === void 0 ? void 0 : _api$table.activeTableMenu;
167
+ var isActiveTableMenuOpen = (activeTableMenu === null || activeTableMenu === void 0 ? void 0 : activeTableMenu.type) === 'row' || (activeTableMenu === null || activeTableMenu === void 0 ? void 0 : activeTableMenu.type) === 'column';
168
+ if (!isActiveTableMenuOpen) {
169
+ return;
170
+ }
171
+ (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref5) {
172
+ var _api$userIntent;
173
+ var tr = _ref5.tr;
174
+ closeActiveTableMenu(api, {
175
+ skipUserIntent: true
176
+ })({
177
+ tr: tr
178
+ });
179
+ (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('default')({
180
+ tr: tr
181
+ });
182
+ return tr;
183
+ });
184
+ }, [api]);
154
185
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
155
186
  type: "button"
156
187
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -176,7 +207,10 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
176
207
  // return focus to editor so copying table selections whilst still works, i cannot call e.preventDefault in a mousemove event as this stops dragstart events from firing
177
208
  // -> this is bad for a11y but is the current standard new copy/paste keyboard shortcuts should be introduced instead
178
209
  editorView.focus();
179
- if (isDragMenuOpen) {
210
+ if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
211
+ // New menu: close the open row/column menu (and show the selection toolbar).
212
+ closeActiveDragMenuAndShowToolbar();
213
+ } else if (isDragMenuOpen) {
180
214
  toggleDragMenu && toggleDragMenu('mouse', e);
181
215
  }
182
216
  },
@@ -20,7 +20,7 @@ import { findTable } from '@atlaskit/editor-tables/utils';
20
20
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
21
21
  import { insertColumnWithAnalytics, insertRowWithAnalytics } from '../../pm-plugins/commands/commands-with-analytics';
22
22
  import { checkIfNumberColumnEnabled } from '../../pm-plugins/utils/nodes';
23
- import { isColumnSelectionWithMergedFirstRow, isRowSelectionWithMergedFirstColumn } from '../../pm-plugins/utils/selection';
23
+ import { isFullRowOrColumnSelected } from '../../pm-plugins/utils/selection';
24
24
  import { TableCssClassName as ClassName } from '../../types';
25
25
  import getPopupOptions from './getPopupOptions';
26
26
  import { DragAndDropInsertButton } from './InsertButton';
@@ -75,7 +75,7 @@ export var FloatingInsertButton = /*#__PURE__*/function (_React$Component) {
75
75
  }
76
76
  var tr = editorView.state.tr;
77
77
  if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
78
- if (tr.selection instanceof CellSelection && (tr.selection.isColSelection() || tr.selection.isRowSelection() || isColumnSelectionWithMergedFirstRow(tr.selection) || isRowSelectionWithMergedFirstColumn(tr.selection))) {
78
+ if (isFullRowOrColumnSelected(tr.selection)) {
79
79
  return null;
80
80
  }
81
81
  } else {
@@ -56,9 +56,6 @@ var FloatingTableMenu = function FloatingTableMenu(_ref) {
56
56
  popupContentRef.current = el;
57
57
  setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 || setOutsideClickTargetRef(el);
58
58
  }, [setOutsideClickTargetRef]);
59
- var dismiss = useCallback(function () {
60
- api === null || api === void 0 || api.core.actions.execute(closeActiveTableMenu(api));
61
- }, [api]);
62
59
  var returnFocusToDragHandle = useCallback(function () {
63
60
  // Match legacy DragMenu's closeMenu('handle') behaviour.
64
61
  var handleId = dragMenuDirection === 'row' ? '#drag-handle-button-row' : '#drag-handle-button-column';
@@ -91,9 +88,9 @@ var FloatingTableMenu = function FloatingTableMenu(_ref) {
91
88
  var handleEscape = useCallback(function (event) {
92
89
  event.preventDefault();
93
90
  event.stopPropagation();
94
- dismiss();
91
+ api === null || api === void 0 || api.core.actions.execute(closeActiveTableMenu(api));
95
92
  returnFocusToDragHandle();
96
- }, [dismiss, returnFocusToDragHandle]);
93
+ }, [api, returnFocusToDragHandle]);
97
94
 
98
95
  // Memoize the editor DOM reference so the provider doesn't re-bind listeners
99
96
  // on every render (the provider depends on `dom` in its effect's deps).
@@ -114,8 +111,8 @@ var FloatingTableMenu = function FloatingTableMenu(_ref) {
114
111
  if (target instanceof Node && (_popupContentRef$curr = popupContentRef.current) !== null && _popupContentRef$curr !== void 0 && _popupContentRef$curr.contains(target) || target instanceof Element && (target.closest(DRAG_HANDLE_CONTROLS_SELECTOR) || target.closest(NESTED_DROPDOWN_SELECTOR))) {
115
112
  return;
116
113
  }
117
- dismiss();
118
- }, [dismiss]);
114
+ api === null || api === void 0 || api.core.actions.execute(closeActiveTableMenu(api));
115
+ }, [api]);
119
116
  if (!isDragMenuOpen || !targetCellPosition || editorView.state.doc.nodeSize <= targetCellPosition) {
120
117
  return null;
121
118
  }
@@ -225,6 +225,7 @@ export var ColumnControls = function ColumnControls(_ref) {
225
225
  },
226
226
  "data-testid": "table-floating-column-".concat(isHover ? colIndex : isPlaceholder ? appearance : selectedColIndexes[0], "-drag-handle")
227
227
  }, /*#__PURE__*/React.createElement(DragHandle, {
228
+ api: api,
228
229
  isDragMenuTarget: !isHover,
229
230
  direction: "column",
230
231
  tableLocalId: localId || '',
@@ -215,6 +215,7 @@ export var DragControls = function DragControls(_ref) {
215
215
  "data-selected-row-index": selectedRowIndexes[0],
216
216
  "data-handle-appearance": appearance
217
217
  }, /*#__PURE__*/React.createElement(DragHandle, {
218
+ api: api,
218
219
  isDragMenuTarget: !isHover,
219
220
  direction: "row",
220
221
  tableLocalId: currentNodeLocalId,
@@ -18,7 +18,7 @@ import { deleteColumns } from '../pm-plugins/transforms/delete-columns';
18
18
  import { deleteRows } from '../pm-plugins/transforms/delete-rows';
19
19
  import { getSelectedCellInfo } from '../pm-plugins/utils/analytics';
20
20
  import { convertHTMLCellIndexToColumnIndex, getColumnIndexByMousePosition, getColumnIndexMappedToColumnIndexInFirstRow } from '../pm-plugins/utils/column-controls';
21
- import { getColumnOrRowIndex, getIndexAttributeSourceElement, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from '../pm-plugins/utils/dom';
21
+ import { getColumnOrRowIndex, getIndexAttributeSourceElement, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton, isTableDragHandleButton } from '../pm-plugins/utils/dom';
22
22
  import { getAllowAddColumnCustomStep } from '../pm-plugins/utils/get-allow-add-column-custom-step';
23
23
  import { getRowIndexByMousePosition } from '../pm-plugins/utils/row-controls';
24
24
  import { TableCssClassName as ClassName, RESIZE_HANDLE_AREA_DECORATION_GAP } from '../types';
@@ -198,14 +198,27 @@ export var handleMouseUp = function handleMouseUp(view, mouseEvent) {
198
198
  }
199
199
  return false;
200
200
  };
201
+ var resetDragHandleSelectedIntentOnMouseDown = function resetDragHandleSelectedIntentOnMouseDown(event, api) {
202
+ var _api$userIntent;
203
+ if (isTableDragHandleButton(event.target)) {
204
+ return;
205
+ }
206
+ if ((api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent) === 'dragHandleSelected') {
207
+ var _api$core, _api$userIntent2;
208
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default'));
209
+ }
210
+ };
201
211
 
202
212
  // Ignore any `mousedown` `event` from control and numbered column buttons
203
213
  // PM end up changing selection during shift selection if not prevented
204
- export var handleMouseDown = function handleMouseDown(_, event) {
214
+ export var handleMouseDown = function handleMouseDown(_view, event, api) {
205
215
  var isControl = !!(event.target && event.target instanceof HTMLElement && (isTableContainerOrWrapper(event.target) || isColumnControlsDecorations(event.target) || isRowControlsButton(event.target) || isDragCornerButton(event.target)));
206
216
  if (isControl) {
207
217
  event.preventDefault();
208
218
  }
219
+ if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
220
+ resetDragHandleSelectedIntentOnMouseDown(event, api);
221
+ }
209
222
  return isControl;
210
223
  };
211
224
  export var handleMouseOut = function handleMouseOut(view, mouseEvent) {
@@ -1,6 +1,8 @@
1
1
  import type { EditorCommand } from '@atlaskit/editor-common/types';
2
2
  import type { ActiveTableMenu, PluginInjectionAPI } from '../../types';
3
- export declare const closeActiveTableMenu: (api?: PluginInjectionAPI | null) => EditorCommand;
3
+ export declare const closeActiveTableMenu: (api?: PluginInjectionAPI | null, options?: {
4
+ skipUserIntent?: boolean;
5
+ }) => EditorCommand;
4
6
  export declare const toggleActiveTableMenu: (activeTableMenu: Exclude<ActiveTableMenu, {
5
7
  type: "none";
6
8
  }>, currentActiveTableMenu: ActiveTableMenu | undefined, api?: PluginInjectionAPI | null) => EditorCommand;
@@ -21,6 +21,7 @@ export declare const isTableContainerOrWrapper: (node: HTMLElement | null) => bo
21
21
  export declare const isDragRowFloatingInsertDot: (node: HTMLElement | null) => boolean;
22
22
  export declare const isDragColumnFloatingInsertDot: (node: HTMLElement | null) => boolean;
23
23
  export declare const isDragCornerButton: (node: HTMLElement | null) => boolean;
24
+ export declare const isTableDragHandleButton: (target: EventTarget | null) => boolean;
24
25
  /**
25
26
  * This can be used with mouse events to determine the left/right side of the target the pointer is closest too.
26
27
  *
@@ -1,4 +1,5 @@
1
- import type { CellSelection } from '@atlaskit/editor-tables/cell-selection';
1
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
2
3
  import type { Rect } from '@atlaskit/editor-tables/table-map';
3
4
  export declare const getSelectedColumnIndexes: (selectionRect: Rect) => number[];
4
5
  export declare const getSelectedRowIndexes: (selectionRect: Rect) => number[];
@@ -14,3 +15,9 @@ export declare const isColumnSelectionWithMergedFirstRow: (selection: CellSelect
14
15
  * returns `false` in this case because the selection does not include the merged first-column cell.
15
16
  */
16
17
  export declare const isRowSelectionWithMergedFirstColumn: (selection: CellSelection) => boolean;
18
+ /**
19
+ * Returns `true` when the selection covers one or more complete rows or columns (the kind of
20
+ * selection produced by clicking a row/column drag handle), including the merged-cell variants
21
+ * where `CellSelection.isRowSelection()` / `isColSelection()` return `false`.
22
+ */
23
+ export declare const isFullRowOrColumnSelected: (selection: Selection) => boolean;
@@ -3,9 +3,10 @@ import React from 'react';
3
3
  import type { WithIntlProps, WrappedComponentProps } from 'react-intl';
4
4
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { TriggerType } from '../../pm-plugins/drag-and-drop/types';
6
- import type { CellHoverMeta, TableDirection } from '../../types';
6
+ import type { CellHoverMeta, PluginInjectionAPI, TableDirection } from '../../types';
7
7
  export type DragHandleAppearance = 'default' | 'selected' | 'disabled' | 'danger' | 'placeholder';
8
8
  type DragHandleProps = {
9
+ api?: PluginInjectionAPI | null;
9
10
  appearance?: DragHandleAppearance;
10
11
  direction?: TableDirection;
11
12
  editorView: EditorView;
@@ -8,7 +8,7 @@ export declare const handleFocus: (view: EditorView, event: Event) => boolean;
8
8
  export declare const handleClick: (view: EditorView, event: Event) => boolean;
9
9
  export declare const handleMouseOver: (view: EditorView, mouseEvent: Event) => boolean;
10
10
  export declare const handleMouseUp: (view: EditorView, mouseEvent: Event) => boolean;
11
- export declare const handleMouseDown: (_: EditorView, event: Event) => boolean;
11
+ export declare const handleMouseDown: (_view: EditorView, event: Event, api?: PluginInjectionAPI | null) => boolean;
12
12
  export declare const handleMouseOut: (view: EditorView, mouseEvent: Event) => boolean;
13
13
  export declare const handleMouseEnter: (view: EditorView, mouseEvent: Event) => boolean;
14
14
  export declare const handleMouseLeave: (view: EditorView, event: Event) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "24.2.3",
3
+ "version": "24.2.4",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -52,7 +52,7 @@
52
52
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.0.0",
53
53
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.0.0",
54
54
  "@atlaskit/primitives": "^20.0.0",
55
- "@atlaskit/tmp-editor-statsig": "^109.1.0",
55
+ "@atlaskit/tmp-editor-statsig": "^109.2.0",
56
56
  "@atlaskit/toggle": "^17.0.0",
57
57
  "@atlaskit/tokens": "^14.0.0",
58
58
  "@atlaskit/tooltip": "^23.0.0",
@@ -67,7 +67,7 @@
67
67
  "uuid": "^3.1.0"
68
68
  },
69
69
  "peerDependencies": {
70
- "@atlaskit/editor-common": "^116.8.0",
70
+ "@atlaskit/editor-common": "^116.10.0",
71
71
  "react": "^18.2.0",
72
72
  "react-dom": "^18.2.0",
73
73
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
@@ -164,6 +164,6 @@
164
164
  "devDependencies": {
165
165
  "react": "^18.2.0",
166
166
  "react-dom": "^18.2.0",
167
- "react-intl": "^6.6.2"
167
+ "react-intl": "^7.0.0"
168
168
  }
169
169
  }