@atlaskit/editor-plugin-table 24.2.2 → 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.
- package/CHANGELOG.md +23 -0
- package/dist/cjs/pm-plugins/commands/active-table-menu.js +14 -5
- package/dist/cjs/pm-plugins/drag-and-drop/plugin.js +3 -1
- package/dist/cjs/pm-plugins/main.js +3 -1
- package/dist/cjs/pm-plugins/utils/column-controls.js +119 -2
- package/dist/cjs/pm-plugins/utils/dom.js +23 -1
- package/dist/cjs/pm-plugins/utils/row-controls.js +43 -1
- package/dist/cjs/pm-plugins/utils/selection.js +74 -1
- package/dist/cjs/ui/DragHandle/index.js +46 -4
- package/dist/cjs/ui/FloatingInsertButton/getPopupOptions.js +19 -5
- package/dist/cjs/ui/FloatingInsertButton/index.js +37 -3
- package/dist/cjs/ui/FloatingTableMenu/index.js +4 -7
- package/dist/cjs/ui/TableFloatingColumnControls/ColumnControls/index.js +26 -15
- package/dist/cjs/ui/TableFloatingColumnControls/index.js +1 -1
- package/dist/cjs/ui/TableFloatingControls/RowControls/DragControls.js +29 -12
- package/dist/cjs/ui/common-styles.js +6 -1
- package/dist/cjs/ui/event-handlers.js +61 -8
- package/dist/es2019/pm-plugins/commands/active-table-menu.js +14 -5
- package/dist/es2019/pm-plugins/drag-and-drop/plugin.js +3 -1
- package/dist/es2019/pm-plugins/main.js +1 -1
- package/dist/es2019/pm-plugins/utils/column-controls.js +114 -2
- package/dist/es2019/pm-plugins/utils/dom.js +20 -0
- package/dist/es2019/pm-plugins/utils/row-controls.js +42 -0
- package/dist/es2019/pm-plugins/utils/selection.js +73 -0
- package/dist/es2019/ui/DragHandle/index.js +47 -4
- package/dist/es2019/ui/FloatingInsertButton/getPopupOptions.js +24 -5
- package/dist/es2019/ui/FloatingInsertButton/index.js +35 -3
- package/dist/es2019/ui/FloatingTableMenu/index.js +4 -7
- package/dist/es2019/ui/TableFloatingColumnControls/ColumnControls/index.js +27 -16
- package/dist/es2019/ui/TableFloatingColumnControls/index.js +2 -2
- package/dist/es2019/ui/TableFloatingControls/RowControls/DragControls.js +30 -12
- package/dist/es2019/ui/common-styles.js +26 -1
- package/dist/es2019/ui/event-handlers.js +61 -8
- package/dist/esm/pm-plugins/commands/active-table-menu.js +14 -5
- package/dist/esm/pm-plugins/drag-and-drop/plugin.js +3 -1
- package/dist/esm/pm-plugins/main.js +3 -1
- package/dist/esm/pm-plugins/utils/column-controls.js +118 -1
- package/dist/esm/pm-plugins/utils/dom.js +22 -0
- package/dist/esm/pm-plugins/utils/row-controls.js +42 -0
- package/dist/esm/pm-plugins/utils/selection.js +73 -0
- package/dist/esm/ui/DragHandle/index.js +47 -5
- package/dist/esm/ui/FloatingInsertButton/getPopupOptions.js +19 -5
- package/dist/esm/ui/FloatingInsertButton/index.js +37 -3
- package/dist/esm/ui/FloatingTableMenu/index.js +4 -7
- package/dist/esm/ui/TableFloatingColumnControls/ColumnControls/index.js +28 -17
- package/dist/esm/ui/TableFloatingColumnControls/index.js +2 -2
- package/dist/esm/ui/TableFloatingControls/RowControls/DragControls.js +31 -14
- package/dist/esm/ui/common-styles.js +7 -2
- package/dist/esm/ui/event-handlers.js +63 -10
- package/dist/types/pm-plugins/commands/active-table-menu.d.ts +3 -1
- package/dist/types/pm-plugins/utils/column-controls.d.ts +35 -1
- package/dist/types/pm-plugins/utils/dom.d.ts +11 -0
- package/dist/types/pm-plugins/utils/row-controls.d.ts +16 -0
- package/dist/types/pm-plugins/utils/selection.d.ts +20 -0
- package/dist/types/ui/DragHandle/index.d.ts +3 -2
- package/dist/types/ui/FloatingInsertButton/getPopupOptions.d.ts +1 -1
- package/dist/types/ui/FloatingInsertButton/index.d.ts +1 -0
- package/dist/types/ui/event-handlers.d.ts +1 -1
- package/package.json +4 -4
|
@@ -13,6 +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 { isFullRowOrColumnSelected } from '../../pm-plugins/utils/selection';
|
|
16
17
|
import { TableCssClassName as ClassName } from '../../types';
|
|
17
18
|
import getPopupOptions from './getPopupOptions';
|
|
18
19
|
import { DragAndDropInsertButton } from './InsertButton';
|
|
@@ -65,8 +66,14 @@ export class FloatingInsertButton extends React.Component {
|
|
|
65
66
|
tr
|
|
66
67
|
}
|
|
67
68
|
} = editorView;
|
|
68
|
-
if (
|
|
69
|
-
|
|
69
|
+
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
70
|
+
if (isFullRowOrColumnSelected(tr.selection)) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
if (tr.selection instanceof CellSelection && (tr.selection.isColSelection() || tr.selection.isRowSelection())) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
70
77
|
}
|
|
71
78
|
const tablePos = findTable(tr.selection);
|
|
72
79
|
if (!tablePos) {
|
|
@@ -120,6 +127,15 @@ export class FloatingInsertButton extends React.Component {
|
|
|
120
127
|
const index = type === 'column' ? insertColumnButtonIndex : insertRowButtonIndex;
|
|
121
128
|
const hasNumberedColumns = checkIfNumberColumnEnabled(editorView.state.selection);
|
|
122
129
|
|
|
130
|
+
// If row 0 has a colspan, anchor to a lower row for the real column boundary (X),
|
|
131
|
+
// then move back up to the table top (Y):
|
|
132
|
+
// row 0: [ colspan=2 ]
|
|
133
|
+
// row 1: [ col 1 ][ col 2 ] ← anchor here for X
|
|
134
|
+
// ↑ button should render at row 0/table top
|
|
135
|
+
let verticalOffsetCorrection = 0;
|
|
136
|
+
if (type === 'column' && expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
137
|
+
verticalOffsetCorrection = Math.max(0, targetCellRef.getBoundingClientRect().top - tableRef.getBoundingClientRect().top);
|
|
138
|
+
}
|
|
123
139
|
// Fixed the 'add column button' not visible issue when sticky header is enabled
|
|
124
140
|
// By setting the Popup z-index higher than the sticky header z-index ( common-styles.ts tr.sticky)
|
|
125
141
|
// Only when inserting a column, otherwise set to undefined
|
|
@@ -137,7 +153,7 @@ export class FloatingInsertButton extends React.Component {
|
|
|
137
153
|
allowOutOfBounds: true
|
|
138
154
|
// Ignored via go/ees005
|
|
139
155
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
140
|
-
}, getPopupOptions(type, index, hasNumberedColumns, tableContainerWrapper), {
|
|
156
|
+
}, getPopupOptions(type, index, hasNumberedColumns, tableContainerWrapper, verticalOffsetCorrection), {
|
|
141
157
|
zIndex: zIndex
|
|
142
158
|
}), /*#__PURE__*/React.createElement(DragAndDropInsertButton, {
|
|
143
159
|
type: type,
|
|
@@ -147,6 +163,18 @@ export class FloatingInsertButton extends React.Component {
|
|
|
147
163
|
isChromelessEditor: isChromelessEditor
|
|
148
164
|
}));
|
|
149
165
|
}
|
|
166
|
+
|
|
167
|
+
// Finds a row where `columnIndex` has real left/right cell boundaries.
|
|
168
|
+
findRowWithUnmergedColumn(tableMap, columnIndex) {
|
|
169
|
+
for (let row = 0; row < tableMap.height; row++) {
|
|
170
|
+
const pos = tableMap.map[row * tableMap.width + columnIndex];
|
|
171
|
+
const rect = tableMap.findCell(pos);
|
|
172
|
+
if (rect.left === columnIndex && rect.right === columnIndex + 1) {
|
|
173
|
+
return row;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
150
178
|
getCellPosition(type, tableNode) {
|
|
151
179
|
const {
|
|
152
180
|
insertColumnButtonIndex,
|
|
@@ -163,6 +191,10 @@ export class FloatingInsertButton extends React.Component {
|
|
|
163
191
|
if (columnIndex > tableMap.width - 1) {
|
|
164
192
|
return null;
|
|
165
193
|
}
|
|
194
|
+
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
195
|
+
const rowWithRealColumn = this.findRowWithUnmergedColumn(tableMap, columnIndex);
|
|
196
|
+
return rowWithRealColumn === null ? null : tableMap.positionAt(rowWithRealColumn, columnIndex, tableNode);
|
|
197
|
+
}
|
|
166
198
|
return tableMap.positionAt(0, columnIndex, tableNode);
|
|
167
199
|
} else {
|
|
168
200
|
// This condition is to make typescript happy.
|
|
@@ -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
|
-
|
|
93
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(closeActiveTableMenu(api));
|
|
97
94
|
returnFocusToDragHandle();
|
|
98
|
-
}, [
|
|
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
|
-
|
|
116
|
-
}, [
|
|
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
|
}
|
|
@@ -8,15 +8,29 @@ import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
|
|
|
8
8
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
9
9
|
import { getSelectionRect } from '@atlaskit/editor-tables/utils';
|
|
10
10
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
11
|
-
import { clearHoverSelection,
|
|
11
|
+
import { clearHoverSelection, hoverCell, hoverColumns, selectColumn, selectColumns, toggleActiveTableMenu } from '../../../pm-plugins/commands';
|
|
12
12
|
import { toggleDragMenuWithAnalytics } from '../../../pm-plugins/drag-and-drop/commands-with-analytics';
|
|
13
13
|
import { getPluginState as getTablePluginState } from '../../../pm-plugins/plugin-factory';
|
|
14
14
|
import { getRowsParams } from '../../../pm-plugins/utils/row-controls';
|
|
15
|
-
import { getSelectedColumnIndexes } from '../../../pm-plugins/utils/selection';
|
|
15
|
+
import { getSelectedColumnIndexes, isColumnSelectionWithMergedFirstRow } from '../../../pm-plugins/utils/selection';
|
|
16
16
|
import { TableCssClassName as ClassName } from '../../../types';
|
|
17
17
|
import { DragHandle } from '../../DragHandle';
|
|
18
18
|
const getSelectedColumns = selection => {
|
|
19
|
-
if (selection instanceof CellSelection
|
|
19
|
+
if (!(selection instanceof CellSelection)) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
23
|
+
// New behaviour: also treat a column selection that sits below a merged first-row cell as a
|
|
24
|
+
// full column selection.
|
|
25
|
+
if (!selection.isColSelection() && !isColumnSelectionWithMergedFirstRow(selection)) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const rect = getSelectionRect(selection);
|
|
29
|
+
return rect ? getSelectedColumnIndexes(rect) : [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Old behaviour: only standard column selections are recognised.
|
|
33
|
+
if (selection.isColSelection()) {
|
|
20
34
|
const rect = getSelectionRect(selection);
|
|
21
35
|
if (!rect) {
|
|
22
36
|
return [];
|
|
@@ -125,27 +139,23 @@ export const ColumnControls = ({
|
|
|
125
139
|
clearHoverSelection()(state, dispatch);
|
|
126
140
|
}
|
|
127
141
|
}, [editorView, tableActive]);
|
|
128
|
-
const toggleDragMenuHandler = useCallback((trigger, event) => {
|
|
142
|
+
const toggleDragMenuHandler = useCallback((trigger, event, handleIndex) => {
|
|
129
143
|
var _api$analytics2;
|
|
144
|
+
if (event !== null && event !== void 0 && event.shiftKey) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
130
147
|
const {
|
|
131
148
|
state,
|
|
132
149
|
dispatch
|
|
133
150
|
} = editorView;
|
|
134
|
-
if (event !== null && event !== void 0 && event.shiftKey) {
|
|
135
|
-
// Shift-click extends the selection rather than toggling the menu, but the
|
|
136
|
-
// open drag menu would otherwise stay anchored to a stale column. Close it here
|
|
137
|
-
// for the updated menu (legacy menu closes via outside-click on its dropdown).
|
|
138
|
-
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
139
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(closeActiveTableMenu(api));
|
|
140
|
-
}
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
151
|
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
144
|
-
|
|
152
|
+
// Use the clicked handle index because `hoveredCell` can point at a merged cell's first column.
|
|
153
|
+
const targetColIndex = handleIndex !== null && handleIndex !== void 0 ? handleIndex : colIndex;
|
|
154
|
+
if (targetColIndex !== undefined && api) {
|
|
145
155
|
const {
|
|
146
156
|
activeTableMenu: currentActiveTableMenu
|
|
147
157
|
} = getTablePluginState(state);
|
|
148
|
-
const isSameActiveMenu = (currentActiveTableMenu === null || currentActiveTableMenu === void 0 ? void 0 : currentActiveTableMenu.type) === 'column' && currentActiveTableMenu.index ===
|
|
158
|
+
const isSameActiveMenu = (currentActiveTableMenu === null || currentActiveTableMenu === void 0 ? void 0 : currentActiveTableMenu.type) === 'column' && currentActiveTableMenu.index === targetColIndex;
|
|
149
159
|
api.core.actions.execute(({
|
|
150
160
|
tr
|
|
151
161
|
}) => {
|
|
@@ -164,7 +174,7 @@ export const ColumnControls = ({
|
|
|
164
174
|
}
|
|
165
175
|
toggleActiveTableMenu({
|
|
166
176
|
type: 'column',
|
|
167
|
-
index:
|
|
177
|
+
index: targetColIndex,
|
|
168
178
|
openedBy: trigger
|
|
169
179
|
}, currentActiveTableMenu, api)({
|
|
170
180
|
tr
|
|
@@ -222,6 +232,7 @@ export const ColumnControls = ({
|
|
|
222
232
|
},
|
|
223
233
|
"data-testid": `table-floating-column-${isHover ? colIndex : isPlaceholder ? appearance : selectedColIndexes[0]}-drag-handle`
|
|
224
234
|
}, /*#__PURE__*/React.createElement(DragHandle, {
|
|
235
|
+
api: api,
|
|
225
236
|
isDragMenuTarget: !isHover,
|
|
226
237
|
direction: "column",
|
|
227
238
|
tableLocalId: localId || '',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
3
3
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
|
-
import { getColumnsWidths } from '../../pm-plugins/utils/column-controls';
|
|
4
|
+
import { getColumnsWidths, getColumnsWidthsWithMergedCells } from '../../pm-plugins/utils/column-controls';
|
|
5
5
|
import { containsHeaderColumn } from '../../pm-plugins/utils/nodes';
|
|
6
6
|
import { getRowHeights } from '../../pm-plugins/utils/row-controls';
|
|
7
7
|
import { isNativeStickySupported } from '../../pm-plugins/utils/sticky-header';
|
|
@@ -63,7 +63,7 @@ const TableFloatingColumnControls = ({
|
|
|
63
63
|
if (!tableRef || !tableActive || isResizing) {
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
|
-
const colWidths = getColumnsWidths(editorView);
|
|
66
|
+
const colWidths = expValEquals('platform_editor_table_menu_updates', 'isEnabled', true) ? getColumnsWidthsWithMergedCells(editorView) : getColumnsWidths(editorView);
|
|
67
67
|
if (stickyTop) {
|
|
68
68
|
var _containerRef$current;
|
|
69
69
|
const columnControlTopOffsetFromParent = '-12px';
|
|
@@ -7,17 +7,31 @@ import { CellSelection } from '@atlaskit/editor-tables';
|
|
|
7
7
|
import { getSelectionRect } from '@atlaskit/editor-tables/utils';
|
|
8
8
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
9
9
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
10
|
-
import { clearHoverSelection,
|
|
10
|
+
import { clearHoverSelection, toggleActiveTableMenu } from '../../../pm-plugins/commands';
|
|
11
11
|
import { toggleDragMenuWithAnalytics } from '../../../pm-plugins/drag-and-drop/commands-with-analytics';
|
|
12
12
|
import { getPluginState as getTablePluginState } from '../../../pm-plugins/plugin-factory';
|
|
13
13
|
import { getRowHeights, getRowsParams } from '../../../pm-plugins/utils/row-controls';
|
|
14
|
-
import { getSelectedRowIndexes } from '../../../pm-plugins/utils/selection';
|
|
14
|
+
import { getSelectedRowIndexes, isRowSelectionWithMergedFirstColumn } from '../../../pm-plugins/utils/selection';
|
|
15
15
|
import { TableCssClassName as ClassName } from '../../../types';
|
|
16
16
|
import { dragRowControlsWidth, dropTargetExtendedWidth } from '../../consts';
|
|
17
17
|
import { DragHandle } from '../../DragHandle';
|
|
18
18
|
import RowDropTarget from '../RowDropTarget';
|
|
19
19
|
const getSelectedRows = selection => {
|
|
20
|
-
if (selection instanceof CellSelection
|
|
20
|
+
if (!(selection instanceof CellSelection)) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
24
|
+
// New behaviour: also treat a row selection that sits to the right of a merged first-column
|
|
25
|
+
// cell as a full row selection.
|
|
26
|
+
if (!selection.isRowSelection() && !isRowSelectionWithMergedFirstColumn(selection)) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const rect = getSelectionRect(selection);
|
|
30
|
+
return rect ? getSelectedRowIndexes(rect) : [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Old behaviour: only standard row selections are recognised.
|
|
34
|
+
if (selection.isRowSelection()) {
|
|
21
35
|
const rect = getSelectionRect(selection);
|
|
22
36
|
if (!rect) {
|
|
23
37
|
return [];
|
|
@@ -78,18 +92,14 @@ export const DragControls = ({
|
|
|
78
92
|
}
|
|
79
93
|
});
|
|
80
94
|
}, [editorView]);
|
|
81
|
-
const toggleDragMenuHandler = useCallback((trigger, event) => {
|
|
95
|
+
const toggleDragMenuHandler = useCallback((trigger, event, handleIndex) => {
|
|
82
96
|
var _api$analytics2;
|
|
83
97
|
if (event !== null && event !== void 0 && event.shiftKey) {
|
|
84
|
-
// Shift-click extends the selection rather than toggling the menu, but the
|
|
85
|
-
// open drag menu would otherwise stay anchored to a stale row. Close it here
|
|
86
|
-
// for the updated menu (legacy menu closes via outside-click on its dropdown).
|
|
87
|
-
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
88
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(closeActiveTableMenu(api));
|
|
89
|
-
}
|
|
90
98
|
return;
|
|
91
99
|
}
|
|
92
|
-
|
|
100
|
+
|
|
101
|
+
// Use the clicked handle index because `hoveredCell` can point at a merged cell's first row.
|
|
102
|
+
const rowIndex = handleIndex !== null && handleIndex !== void 0 ? handleIndex : hoveredCell === null || hoveredCell === void 0 ? void 0 : hoveredCell.rowIndex;
|
|
93
103
|
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
94
104
|
if (rowIndex !== undefined && api) {
|
|
95
105
|
const {
|
|
@@ -205,6 +215,7 @@ export const DragControls = ({
|
|
|
205
215
|
"data-selected-row-index": selectedRowIndexes[0],
|
|
206
216
|
"data-handle-appearance": appearance
|
|
207
217
|
}, /*#__PURE__*/React.createElement(DragHandle, {
|
|
218
|
+
api: api,
|
|
208
219
|
isDragMenuTarget: !isHover,
|
|
209
220
|
direction: "row",
|
|
210
221
|
tableLocalId: currentNodeLocalId,
|
|
@@ -230,10 +241,17 @@ export const DragControls = ({
|
|
|
230
241
|
if (!tableActive) {
|
|
231
242
|
return null;
|
|
232
243
|
}
|
|
244
|
+
const selectedAppearance = isRowSelected && isEntireTableSelected ? isInDanger ? 'danger' : 'selected' : 'placeholder';
|
|
233
245
|
|
|
234
246
|
// placeholder / selected need to always render at least one handle
|
|
235
247
|
// so it can be focused via keyboard shortcuts
|
|
236
|
-
|
|
248
|
+
const selectedGridRow = expValEquals('platform_editor_table_menu_updates', 'isEnabled', true) ?
|
|
249
|
+
// New behaviour: always position the placeholder in the first row to avoid an invalid
|
|
250
|
+
// `NaN / span 0` grid placement (which makes the handle disappear) when no rows are selected.
|
|
251
|
+
selectedAppearance === 'placeholder' ? '1 / span 1' : `${selectedRowIndexes[0] + 1} / span ${selectedRowIndexes.length}` :
|
|
252
|
+
// Old behaviour.
|
|
253
|
+
`${selectedRowIndexes[0] + 1} / span ${selectedRowIndexes.length}`;
|
|
254
|
+
handles.push(generateHandleByType('selected', selectedAppearance, selectedGridRow, selectedRowIndexes));
|
|
237
255
|
if (hoveredCell && isTableHovered && rowIndex !== undefined && !selectedRowIndexes.includes(rowIndex) && rowIndex < rowHeights.length) {
|
|
238
256
|
handles.push(generateHandleByType('hover', 'default', `${rowIndex + 1} / span 1`, rowIndexes));
|
|
239
257
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
7
7
|
import { css } from '@emotion/react';
|
|
8
8
|
import { getBrowserInfo } from '@atlaskit/editor-common/browser';
|
|
9
|
-
import { ANCHOR_VARIABLE_NAME, tableMarginTop, tableSharedStyle, TableSharedCssClassName } from '@atlaskit/editor-common/styles';
|
|
9
|
+
import { ANCHOR_VARIABLE_NAME, DRAG_HANDLE_WIDTH, tableMarginTop, tableSharedStyle, TableSharedCssClassName } from '@atlaskit/editor-common/styles';
|
|
10
10
|
import { SORTABLE_COLUMN_ICON_CLASSNAME } from '@atlaskit/editor-common/table';
|
|
11
11
|
import { akEditorSelectedNodeClassName, akEditorSmallZIndex, akEditorStickyHeaderZIndex, akEditorTableCellOnStickyHeaderZIndex, akEditorTableNumberColumnWidth, akEditorTableToolbarSize, akEditorUnitZIndex, getSelectionStyles, MAX_BROWSER_SCROLLBAR_HEIGHT, SelectionStyle, relativeSizeToBaseFontSize, relativeFontSizeToBase16, akEditorSelectedBorderColor } from '@atlaskit/editor-shared-styles';
|
|
12
12
|
import { akEditorTableContainerBg } from '@atlaskit/editor-shared-styles/consts';
|
|
@@ -425,6 +425,31 @@ const baseTableStylesWithoutSharedStyle = props => css`
|
|
|
425
425
|
width: ${insertColumnButtonOffset + 1}px;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
+
/* use :before element to hide table row insert dots when legacy table sticky header is activated */
|
|
429
|
+
${expValEquals('platform_editor_table_col_insert', 'isEnabled', true) ?
|
|
430
|
+
// Mask geometry mirrors the drag-handle wrapper geometry from
|
|
431
|
+
// editor-plugin-block-controls/src/ui/drag-handle.tsx
|
|
432
|
+
// (`buttonWrapperStyles`):
|
|
433
|
+
// height = paddingTop (=calc(space.400 - 1px)) + paddingBottom (=space.200) + DRAG_HANDLE_HEIGHT
|
|
434
|
+
// width = DRAG_HANDLE_WIDTH + paddingRight('space.150')
|
|
435
|
+
`.${ClassName.TABLE_CONTAINER}.${ClassName.TABLE_STICKY}:has(tr.sticky)::before {
|
|
436
|
+
content: ' ';
|
|
437
|
+
position: sticky;
|
|
438
|
+
pointer-events: none;
|
|
439
|
+
top: 0;
|
|
440
|
+
float: left;
|
|
441
|
+
transform: translateX(calc(-1 * (${DRAG_HANDLE_WIDTH}px + ${"var(--ds-space-150, 12px)"})));
|
|
442
|
+
margin-bottom: calc(-1 * (${"var(--ds-space-400, 32px)"} - 1px + ${"var(--ds-space-200, 16px)"} + ${"var(--ds-space-300, 24px)"}));
|
|
443
|
+
height: calc(${"var(--ds-space-400, 32px)"} - 1px + ${"var(--ds-space-200, 16px)"} + ${"var(--ds-space-300, 24px)"});
|
|
444
|
+
width: calc(${DRAG_HANDLE_WIDTH}px + ${"var(--ds-space-150, 12px)"});
|
|
445
|
+
background: linear-gradient(
|
|
446
|
+
to bottom,
|
|
447
|
+
${expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? `var(${akEditorTableContainerBg}, ${"var(--ds-surface, #FFFFFF)"})` : "var(--ds-surface, #FFFFFF)"} 90%,
|
|
448
|
+
transparent
|
|
449
|
+
);
|
|
450
|
+
z-index: ${rowControlsZIndex + 5};
|
|
451
|
+
}` : ``}
|
|
452
|
+
|
|
428
453
|
/* To fix jumpiness caused in Chrome Browsers for sticky headers */
|
|
429
454
|
.${ClassName.TABLE_STICKY} .sticky + tr {
|
|
430
455
|
min-height: 0px;
|
|
@@ -16,9 +16,10 @@ import { getPluginState as getResizePluginState } from '../pm-plugins/table-resi
|
|
|
16
16
|
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
|
-
import { convertHTMLCellIndexToColumnIndex, getColumnIndexMappedToColumnIndexInFirstRow } from '../pm-plugins/utils/column-controls';
|
|
20
|
-
import { getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from '../pm-plugins/utils/dom';
|
|
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, isTableDragHandleButton } from '../pm-plugins/utils/dom';
|
|
21
21
|
import { getAllowAddColumnCustomStep } from '../pm-plugins/utils/get-allow-add-column-custom-step';
|
|
22
|
+
import { getRowIndexByMousePosition } from '../pm-plugins/utils/row-controls';
|
|
22
23
|
import { TableCssClassName as ClassName, RESIZE_HANDLE_AREA_DECORATION_GAP } from '../types';
|
|
23
24
|
import { TABLE_MENU_SELECTOR } from './TableMenu/shared/consts';
|
|
24
25
|
const isFocusingCalendar = event => event instanceof FocusEvent && event.relatedTarget instanceof HTMLElement && event.relatedTarget.getAttribute('aria-label') === 'calendar';
|
|
@@ -196,14 +197,27 @@ export const handleMouseUp = (view, mouseEvent) => {
|
|
|
196
197
|
}
|
|
197
198
|
return false;
|
|
198
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
|
+
};
|
|
199
210
|
|
|
200
211
|
// Ignore any `mousedown` `event` from control and numbered column buttons
|
|
201
212
|
// PM end up changing selection during shift selection if not prevented
|
|
202
|
-
export const handleMouseDown = (
|
|
213
|
+
export const handleMouseDown = (_view, event, api) => {
|
|
203
214
|
const isControl = !!(event.target && event.target instanceof HTMLElement && (isTableContainerOrWrapper(event.target) || isColumnControlsDecorations(event.target) || isRowControlsButton(event.target) || isDragCornerButton(event.target)));
|
|
204
215
|
if (isControl) {
|
|
205
216
|
event.preventDefault();
|
|
206
217
|
}
|
|
218
|
+
if (expValEquals('platform_editor_table_menu_updates', 'isEnabled', true)) {
|
|
219
|
+
resetDragHandleSelectedIntentOnMouseDown(event, api);
|
|
220
|
+
}
|
|
207
221
|
return isControl;
|
|
208
222
|
};
|
|
209
223
|
export const handleMouseOut = (view, mouseEvent) => {
|
|
@@ -292,6 +306,19 @@ const handleMouseMoveDebounce = nodeViewPortalProviderAPI => rafSchedule((view,
|
|
|
292
306
|
return false;
|
|
293
307
|
}
|
|
294
308
|
const element = event.target;
|
|
309
|
+
const isTableMenuUpdatesEnabled = expValEquals('platform_editor_table_menu_updates', 'isEnabled', true);
|
|
310
|
+
|
|
311
|
+
// Spanned cells need mouse-position-based hover indexes; normal cells already report them.
|
|
312
|
+
if (isTableMenuUpdatesEnabled) {
|
|
313
|
+
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
314
|
+
const tableCell = isElementInTableCell(element);
|
|
315
|
+
if (tableCell && (tableCell.rowSpan > 1 || tableCell.colSpan > 1)) {
|
|
316
|
+
const dragDropState = getDragDropPluginState(view.state);
|
|
317
|
+
if (dragDropState && !dragDropState.isDragging) {
|
|
318
|
+
trackCellLocation(view, event);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
295
322
|
if (isColumnControlsDecorations(element) || isDragColumnFloatingInsertDot(element)) {
|
|
296
323
|
const {
|
|
297
324
|
state,
|
|
@@ -300,7 +327,8 @@ const handleMouseMoveDebounce = nodeViewPortalProviderAPI => rafSchedule((view,
|
|
|
300
327
|
const {
|
|
301
328
|
insertColumnButtonIndex
|
|
302
329
|
} = getPluginState(state);
|
|
303
|
-
const
|
|
330
|
+
const indexSourceElement = isTableMenuUpdatesEnabled ? getIndexAttributeSourceElement(element) : element;
|
|
331
|
+
const [startIndex, endIndex] = getColumnOrRowIndex(indexSourceElement);
|
|
304
332
|
const positionColumn = getMousePositionHorizontalRelativeByElement(event, offsetX, undefined) === 'right' ? endIndex : startIndex;
|
|
305
333
|
if (positionColumn !== insertColumnButtonIndex) {
|
|
306
334
|
return showInsertColumnButton(positionColumn)(state, dispatch);
|
|
@@ -314,7 +342,8 @@ const handleMouseMoveDebounce = nodeViewPortalProviderAPI => rafSchedule((view,
|
|
|
314
342
|
const {
|
|
315
343
|
insertRowButtonIndex
|
|
316
344
|
} = getPluginState(state);
|
|
317
|
-
const
|
|
345
|
+
const indexSourceElement = isTableMenuUpdatesEnabled ? getIndexAttributeSourceElement(element) : element;
|
|
346
|
+
const [startIndex, endIndex] = getColumnOrRowIndex(indexSourceElement);
|
|
318
347
|
const positionRow = getMousePositionVerticalRelativeByElement(event) === 'bottom' ? endIndex : startIndex;
|
|
319
348
|
if (positionRow !== insertRowButtonIndex) {
|
|
320
349
|
return showInsertRowButton(positionRow)(state, dispatch);
|
|
@@ -462,7 +491,8 @@ export const whenTableInFocus = (eventHandler, pluginInjectionApi) => (view, mou
|
|
|
462
491
|
return eventHandler(view, mouseEvent);
|
|
463
492
|
};
|
|
464
493
|
const trackCellLocation = (view, mouseEvent) => {
|
|
465
|
-
var _tableElement$dataset;
|
|
494
|
+
var _tableElement$dataset, _getRowIndexByMousePo;
|
|
495
|
+
const isTableMenuUpdatesEnabled = expValEquals('platform_editor_table_menu_updates', 'isEnabled', true);
|
|
466
496
|
const target = mouseEvent.target;
|
|
467
497
|
// Ignored via go/ees005
|
|
468
498
|
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
@@ -488,13 +518,36 @@ const trackCellLocation = (view, mouseEvent) => {
|
|
|
488
518
|
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
489
519
|
const rowElement = closestElement(target, 'tr');
|
|
490
520
|
const htmlRowIndex = rowElement && rowElement.rowIndex;
|
|
521
|
+
const rowIndex = maybeTableCell.rowSpan > 1 && mouseEvent instanceof MouseEvent && isTableMenuUpdatesEnabled ? (_getRowIndexByMousePo = getRowIndexByMousePosition(tableRef, mouseEvent, {
|
|
522
|
+
startIndex: htmlRowIndex,
|
|
523
|
+
endIndex: htmlRowIndex + maybeTableCell.rowSpan
|
|
524
|
+
})) !== null && _getRowIndexByMousePo !== void 0 ? _getRowIndexByMousePo : htmlRowIndex : htmlRowIndex;
|
|
491
525
|
const tableMap = tableNode && TableMap.get(tableNode);
|
|
492
526
|
let colIndex = htmlColIndex;
|
|
493
527
|
if (tableMap) {
|
|
494
528
|
const convertedColIndex = convertHTMLCellIndexToColumnIndex(htmlColIndex, htmlRowIndex, tableMap);
|
|
495
|
-
|
|
529
|
+
if (isTableMenuUpdatesEnabled) {
|
|
530
|
+
// New behaviour: the column controls grid renders one track per visual column
|
|
531
|
+
// (`getColumnsWidthsWithMergedCells`), so the hover index must be the visual column
|
|
532
|
+
// index — not the first-row-cell index. Mapping to the first-row cell would collapse
|
|
533
|
+
// every column under a merged first-row cell to the same index, leaving the drag handle
|
|
534
|
+
// stuck when hovering cells in other rows. For a colspanned cell, refine the converted
|
|
535
|
+
// (left-most) visual column to the exact visual column under the pointer.
|
|
536
|
+
colIndex = convertedColIndex;
|
|
537
|
+
if (maybeTableCell.colSpan > 1 && mouseEvent instanceof MouseEvent) {
|
|
538
|
+
var _getColumnIndexByMous;
|
|
539
|
+
colIndex = (_getColumnIndexByMous = getColumnIndexByMousePosition(maybeTableCell, mouseEvent, {
|
|
540
|
+
startIndex: convertedColIndex,
|
|
541
|
+
endIndex: convertedColIndex + maybeTableCell.colSpan
|
|
542
|
+
})) !== null && _getColumnIndexByMous !== void 0 ? _getColumnIndexByMous : convertedColIndex;
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
// Old behaviour: the legacy grid renders one track per first-row cell, so snap to the
|
|
546
|
+
// first-row column index (a merged first-row cell collapses to a single column track).
|
|
547
|
+
colIndex = getColumnIndexMappedToColumnIndexInFirstRow(convertedColIndex, htmlRowIndex, tableMap);
|
|
548
|
+
}
|
|
496
549
|
}
|
|
497
|
-
hoverCell(
|
|
550
|
+
hoverCell(rowIndex, colIndex)(view.state, view.dispatch);
|
|
498
551
|
};
|
|
499
552
|
export const withCellTracking = eventHandler => (view, mouseEvent) => {
|
|
500
553
|
if (getDragDropPluginState(view.state) && !getDragDropPluginState(view.state).isDragging) {
|
|
@@ -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$
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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(
|
|
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,
|