@atlaskit/editor-plugin-table 5.4.12 → 5.4.13

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 5.4.13
4
+
5
+ ### Patch Changes
6
+
7
+ - [#58379](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/58379) [`985c068738e8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/985c068738e8) - [ux] Add a util to convert cell index into actula colIndex to fix column drag handle position.
8
+ - Updated dependencies
9
+
3
10
  ## 5.4.12
4
11
 
5
12
  ### Patch Changes
@@ -348,13 +348,19 @@ var trackCellLocation = function trackCellLocation(view, mouseEvent) {
348
348
  if (!maybeTableCell || !tableRef) {
349
349
  return;
350
350
  }
351
- var colIndex = maybeTableCell.cellIndex;
351
+ var htmlColIndex = maybeTableCell.cellIndex;
352
352
  var rowElement = (0, _utils.closestElement)(target, 'tr');
353
- var rowIndex = rowElement && rowElement.rowIndex;
353
+ var htmlRowIndex = rowElement && rowElement.rowIndex;
354
354
  var colHeight = tableRef.offsetHeight;
355
355
  var colWidth = maybeTableCell.offsetWidth;
356
- if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== rowIndex || hoveredCell.colWidth !== colWidth || hoveredCell.colHeight !== colHeight) {
357
- (0, _commands.hoverCell)(rowIndex, colIndex, colWidth, colHeight)(view.state, view.dispatch);
356
+ var tableMap = tableNode && _tableMap.TableMap.get(tableNode);
357
+ var colIndex = htmlColIndex;
358
+ if (tableMap) {
359
+ var convertedColIndex = (0, _utils3.convertHTMLCellIndexToColumnIndex)(htmlColIndex, htmlRowIndex, tableMap);
360
+ colIndex = (0, _utils3.getColumnIndexMappedToColumnIndexInFirstRow)(convertedColIndex, htmlRowIndex, tableMap);
361
+ }
362
+ if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== htmlRowIndex || hoveredCell.colWidth !== colWidth || hoveredCell.colHeight !== colHeight) {
363
+ (0, _commands.hoverCell)(htmlRowIndex, colIndex, colWidth, colHeight)(view.state, view.dispatch);
358
364
  }
359
365
  };
360
366
  var withCellTracking = exports.withCellTracking = function withCellTracking(eventHandler, elementContentRects) {
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.isColumnDeleteButtonVisible = exports.getColumnsWidths = exports.getColumnDeleteButtonParams = exports.getColumnClassNames = exports.colWidthsForRow = void 0;
7
+ exports.isColumnDeleteButtonVisible = exports.getColumnsWidths = exports.getColumnIndexMappedToColumnIndexInFirstRow = exports.getColumnDeleteButtonParams = exports.getColumnClassNames = exports.convertHTMLCellIndexToColumnIndex = exports.colWidthsForRow = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _utils = require("@atlaskit/editor-common/utils");
10
10
  var _utils2 = require("@atlaskit/editor-prosemirror/utils");
@@ -189,4 +189,66 @@ var colWidthsForRow = exports.colWidthsForRow = function colWidthsForRow(tr) {
189
189
  return pctWidths.map(function (pct) {
190
190
  return "".concat(pct, "%");
191
191
  }).join(' ');
192
+ };
193
+ var convertHTMLCellIndexToColumnIndex = exports.convertHTMLCellIndexToColumnIndex = function convertHTMLCellIndexToColumnIndex(htmlColIndex, htmlRowIndex, tableMap) {
194
+ // Same numbers (positions) in tableMap.map array mean that there are merged cells.
195
+ // Cells can be merged across columns. So we need to check if the cell on the left and current cell have the same value.
196
+ // Cells can be merged acroll rows. So we need to check if the cell above has the same value as current cell.
197
+ // When cell has the same value as the cell above it or the cell to the left of it, html cellIndex won't count it a separete column.
198
+ var width = tableMap.width;
199
+ var map = tableMap.map;
200
+ var htmlColCount = 0;
201
+ if (htmlRowIndex === 0) {
202
+ for (var colIndex = 0; colIndex < width; colIndex++) {
203
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
204
+ htmlColCount++;
205
+ }
206
+ if (htmlColCount - 1 === htmlColIndex) {
207
+ return colIndex;
208
+ }
209
+ }
210
+ } else {
211
+ for (var _colIndex = 0; _colIndex < width; _colIndex++) {
212
+ var currentCellMapIndex = htmlRowIndex * width + _colIndex;
213
+ var cellAboveMapIndex = (htmlRowIndex - 1) * width + _colIndex;
214
+ if (_colIndex > 0) {
215
+ if (map[currentCellMapIndex] !== map[currentCellMapIndex - 1] && map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
216
+ htmlColCount++;
217
+ }
218
+ } else {
219
+ if (map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
220
+ htmlColCount++;
221
+ }
222
+ }
223
+ if (htmlColCount - 1 === htmlColIndex) {
224
+ return _colIndex;
225
+ }
226
+ }
227
+ }
228
+ return 0;
229
+ };
230
+
231
+ // When first row has merged cells, our converted column index needs to be mapped.
232
+ var getColumnIndexMappedToColumnIndexInFirstRow = exports.getColumnIndexMappedToColumnIndexInFirstRow = function getColumnIndexMappedToColumnIndexInFirstRow(convertedColIndex, htmlRowIndex, tableMap) {
233
+ var width = tableMap.width;
234
+ var map = tableMap.map;
235
+ var mapColIndexToFistRowColIndex = [];
236
+ var htmlColCounFirstRow = 0;
237
+ var colSpan = 0;
238
+ if (htmlRowIndex === 0) {
239
+ return convertedColIndex;
240
+ }
241
+ for (var colIndex = 0; colIndex < width; colIndex++) {
242
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
243
+ if (colSpan > 0) {
244
+ htmlColCounFirstRow += colSpan;
245
+ colSpan = 0;
246
+ }
247
+ htmlColCounFirstRow++;
248
+ } else if (map[colIndex] === map[colIndex - 1]) {
249
+ colSpan++;
250
+ }
251
+ mapColIndexToFistRowColIndex[colIndex] = htmlColCounFirstRow - 1;
252
+ }
253
+ return mapColIndexToFistRowColIndex[convertedColIndex];
192
254
  };
@@ -39,6 +39,12 @@ Object.defineProperty(exports, "containsHeaderRow", {
39
39
  return _nodes.containsHeaderRow;
40
40
  }
41
41
  });
42
+ Object.defineProperty(exports, "convertHTMLCellIndexToColumnIndex", {
43
+ enumerable: true,
44
+ get: function get() {
45
+ return _columnControls.convertHTMLCellIndexToColumnIndex;
46
+ }
47
+ });
42
48
  Object.defineProperty(exports, "copyPreviousRow", {
43
49
  enumerable: true,
44
50
  get: function get() {
@@ -111,6 +117,12 @@ Object.defineProperty(exports, "getColumnDeleteButtonParams", {
111
117
  return _columnControls.getColumnDeleteButtonParams;
112
118
  }
113
119
  });
120
+ Object.defineProperty(exports, "getColumnIndexMappedToColumnIndexInFirstRow", {
121
+ enumerable: true,
122
+ get: function get() {
123
+ return _columnControls.getColumnIndexMappedToColumnIndexInFirstRow;
124
+ }
125
+ });
114
126
  Object.defineProperty(exports, "getColumnOrRowIndex", {
115
127
  enumerable: true,
116
128
  get: function get() {
@@ -10,7 +10,7 @@ import { getPluginState } from './pm-plugins/plugin-factory';
10
10
  import { getPluginState as getResizePluginState } from './pm-plugins/table-resizing/plugin-factory';
11
11
  import { deleteColumns, deleteRows } from './transforms';
12
12
  import { RESIZE_HANDLE_AREA_DECORATION_GAP } from './types';
13
- import { getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, getSelectedCellInfo, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from './utils';
13
+ import { convertHTMLCellIndexToColumnIndex, getColumnIndexMappedToColumnIndexInFirstRow, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, getSelectedCellInfo, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from './utils';
14
14
  import { getAllowAddColumnCustomStep } from './utils/get-allow-add-column-custom-step';
15
15
  const isFocusingCalendar = event => event instanceof FocusEvent && event.relatedTarget instanceof HTMLElement && event.relatedTarget.getAttribute('aria-label') === 'calendar';
16
16
  const isFocusingModal = event => event instanceof FocusEvent && event.relatedTarget instanceof HTMLElement && event.relatedTarget.closest('[role="dialog"]');
@@ -356,13 +356,19 @@ const trackCellLocation = (view, mouseEvent) => {
356
356
  if (!maybeTableCell || !tableRef) {
357
357
  return;
358
358
  }
359
- const colIndex = maybeTableCell.cellIndex;
359
+ const htmlColIndex = maybeTableCell.cellIndex;
360
360
  const rowElement = closestElement(target, 'tr');
361
- const rowIndex = rowElement && rowElement.rowIndex;
361
+ const htmlRowIndex = rowElement && rowElement.rowIndex;
362
362
  const colHeight = tableRef.offsetHeight;
363
363
  const colWidth = maybeTableCell.offsetWidth;
364
- if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== rowIndex || hoveredCell.colWidth !== colWidth || hoveredCell.colHeight !== colHeight) {
365
- hoverCell(rowIndex, colIndex, colWidth, colHeight)(view.state, view.dispatch);
364
+ const tableMap = tableNode && TableMap.get(tableNode);
365
+ let colIndex = htmlColIndex;
366
+ if (tableMap) {
367
+ const convertedColIndex = convertHTMLCellIndexToColumnIndex(htmlColIndex, htmlRowIndex, tableMap);
368
+ colIndex = getColumnIndexMappedToColumnIndexInFirstRow(convertedColIndex, htmlRowIndex, tableMap);
369
+ }
370
+ if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== htmlRowIndex || hoveredCell.colWidth !== colWidth || hoveredCell.colHeight !== colHeight) {
371
+ hoverCell(htmlRowIndex, colIndex, colWidth, colHeight)(view.state, view.dispatch);
366
372
  }
367
373
  };
368
374
  export const withCellTracking = (eventHandler, elementContentRects) => (view, mouseEvent) => {
@@ -159,4 +159,66 @@ export const colWidthsForRow = tr => {
159
159
  const visualColCount = rowColSpans.reduce((acc, val) => acc + val, 0);
160
160
  const pctWidths = rowColSpans.map(cellColSpan => cellColSpan / visualColCount * 100);
161
161
  return pctWidths.map(pct => `${pct}%`).join(' ');
162
+ };
163
+ export const convertHTMLCellIndexToColumnIndex = (htmlColIndex, htmlRowIndex, tableMap) => {
164
+ // Same numbers (positions) in tableMap.map array mean that there are merged cells.
165
+ // Cells can be merged across columns. So we need to check if the cell on the left and current cell have the same value.
166
+ // Cells can be merged acroll rows. So we need to check if the cell above has the same value as current cell.
167
+ // When cell has the same value as the cell above it or the cell to the left of it, html cellIndex won't count it a separete column.
168
+ const width = tableMap.width;
169
+ const map = tableMap.map;
170
+ let htmlColCount = 0;
171
+ if (htmlRowIndex === 0) {
172
+ for (let colIndex = 0; colIndex < width; colIndex++) {
173
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
174
+ htmlColCount++;
175
+ }
176
+ if (htmlColCount - 1 === htmlColIndex) {
177
+ return colIndex;
178
+ }
179
+ }
180
+ } else {
181
+ for (let colIndex = 0; colIndex < width; colIndex++) {
182
+ const currentCellMapIndex = htmlRowIndex * width + colIndex;
183
+ const cellAboveMapIndex = (htmlRowIndex - 1) * width + colIndex;
184
+ if (colIndex > 0) {
185
+ if (map[currentCellMapIndex] !== map[currentCellMapIndex - 1] && map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
186
+ htmlColCount++;
187
+ }
188
+ } else {
189
+ if (map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
190
+ htmlColCount++;
191
+ }
192
+ }
193
+ if (htmlColCount - 1 === htmlColIndex) {
194
+ return colIndex;
195
+ }
196
+ }
197
+ }
198
+ return 0;
199
+ };
200
+
201
+ // When first row has merged cells, our converted column index needs to be mapped.
202
+ export const getColumnIndexMappedToColumnIndexInFirstRow = (convertedColIndex, htmlRowIndex, tableMap) => {
203
+ const width = tableMap.width;
204
+ const map = tableMap.map;
205
+ const mapColIndexToFistRowColIndex = [];
206
+ let htmlColCounFirstRow = 0;
207
+ let colSpan = 0;
208
+ if (htmlRowIndex === 0) {
209
+ return convertedColIndex;
210
+ }
211
+ for (let colIndex = 0; colIndex < width; colIndex++) {
212
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
213
+ if (colSpan > 0) {
214
+ htmlColCounFirstRow += colSpan;
215
+ colSpan = 0;
216
+ }
217
+ htmlColCounFirstRow++;
218
+ } else if (map[colIndex] === map[colIndex - 1]) {
219
+ colSpan++;
220
+ }
221
+ mapColIndexToFistRowColIndex[colIndex] = htmlColCounFirstRow - 1;
222
+ }
223
+ return mapColIndexToFistRowColIndex[convertedColIndex];
162
224
  };
@@ -3,7 +3,7 @@ export { findControlsHoverDecoration, createControlsHoverDecoration, createColum
3
3
  export { isIsolating, containsHeaderColumn, containsHeaderRow, checkIfHeaderColumnEnabled, checkIfHeaderRowEnabled, checkIfNumberColumnEnabled, isLayoutSupported, getTableWidth, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns, isTableNested, anyChildCellMergedAcrossRow, supportedHeaderRow } from './nodes';
4
4
  export { unwrapContentFromTable, removeTableFromFirstChild, removeTableFromLastChild, transformSliceToRemoveOpenTable, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell } from './paste';
5
5
  export { isCell, isCornerButton, isInsertRowButton, isColumnControlsDecorations, isTableControlsButton, isTableContainerOrWrapper, isRowControlsButton, isDragRowControlsButton, isDragColumnFloatingInsertDot, isDragRowFloatingInsertDot, isDragCornerButton, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, updateResizeHandles, isResizeHandleDecoration, hasResizeHandler } from './dom';
6
- export { getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames } from './column-controls';
6
+ export { convertHTMLCellIndexToColumnIndex, getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames, getColumnIndexMappedToColumnIndexInFirstRow } from './column-controls';
7
7
  export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getRowsParams, getRowClassNames, copyPreviousRow } from './row-controls';
8
8
  export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
9
9
  export { getMergedCellsPositions } from './table';
@@ -11,7 +11,7 @@ import { getPluginState } from './pm-plugins/plugin-factory';
11
11
  import { getPluginState as getResizePluginState } from './pm-plugins/table-resizing/plugin-factory';
12
12
  import { deleteColumns, deleteRows } from './transforms';
13
13
  import { RESIZE_HANDLE_AREA_DECORATION_GAP } from './types';
14
- import { getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, getSelectedCellInfo, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from './utils';
14
+ import { convertHTMLCellIndexToColumnIndex, getColumnIndexMappedToColumnIndexInFirstRow, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, getSelectedCellInfo, hasResizeHandler, isCell, isColumnControlsDecorations, isCornerButton, isDragColumnFloatingInsertDot, isDragCornerButton, isDragRowFloatingInsertDot, isInsertRowButton, isResizeHandleDecoration, isRowControlsButton, isTableContainerOrWrapper, isTableControlsButton } from './utils';
15
15
  import { getAllowAddColumnCustomStep } from './utils/get-allow-add-column-custom-step';
16
16
  var isFocusingCalendar = function isFocusingCalendar(event) {
17
17
  return event instanceof FocusEvent && event.relatedTarget instanceof HTMLElement && event.relatedTarget.getAttribute('aria-label') === 'calendar';
@@ -339,13 +339,19 @@ var trackCellLocation = function trackCellLocation(view, mouseEvent) {
339
339
  if (!maybeTableCell || !tableRef) {
340
340
  return;
341
341
  }
342
- var colIndex = maybeTableCell.cellIndex;
342
+ var htmlColIndex = maybeTableCell.cellIndex;
343
343
  var rowElement = closestElement(target, 'tr');
344
- var rowIndex = rowElement && rowElement.rowIndex;
344
+ var htmlRowIndex = rowElement && rowElement.rowIndex;
345
345
  var colHeight = tableRef.offsetHeight;
346
346
  var colWidth = maybeTableCell.offsetWidth;
347
- if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== rowIndex || hoveredCell.colWidth !== colWidth || hoveredCell.colHeight !== colHeight) {
348
- hoverCell(rowIndex, colIndex, colWidth, colHeight)(view.state, view.dispatch);
347
+ var tableMap = tableNode && TableMap.get(tableNode);
348
+ var colIndex = htmlColIndex;
349
+ if (tableMap) {
350
+ var convertedColIndex = convertHTMLCellIndexToColumnIndex(htmlColIndex, htmlRowIndex, tableMap);
351
+ colIndex = getColumnIndexMappedToColumnIndexInFirstRow(convertedColIndex, htmlRowIndex, tableMap);
352
+ }
353
+ if (hoveredCell.colIndex !== colIndex || hoveredCell.rowIndex !== htmlRowIndex || hoveredCell.colWidth !== colWidth || hoveredCell.colHeight !== colHeight) {
354
+ hoverCell(htmlRowIndex, colIndex, colWidth, colHeight)(view.state, view.dispatch);
349
355
  }
350
356
  };
351
357
  export var withCellTracking = function withCellTracking(eventHandler, elementContentRects) {
@@ -182,4 +182,66 @@ export var colWidthsForRow = function colWidthsForRow(tr) {
182
182
  return pctWidths.map(function (pct) {
183
183
  return "".concat(pct, "%");
184
184
  }).join(' ');
185
+ };
186
+ export var convertHTMLCellIndexToColumnIndex = function convertHTMLCellIndexToColumnIndex(htmlColIndex, htmlRowIndex, tableMap) {
187
+ // Same numbers (positions) in tableMap.map array mean that there are merged cells.
188
+ // Cells can be merged across columns. So we need to check if the cell on the left and current cell have the same value.
189
+ // Cells can be merged acroll rows. So we need to check if the cell above has the same value as current cell.
190
+ // When cell has the same value as the cell above it or the cell to the left of it, html cellIndex won't count it a separete column.
191
+ var width = tableMap.width;
192
+ var map = tableMap.map;
193
+ var htmlColCount = 0;
194
+ if (htmlRowIndex === 0) {
195
+ for (var colIndex = 0; colIndex < width; colIndex++) {
196
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
197
+ htmlColCount++;
198
+ }
199
+ if (htmlColCount - 1 === htmlColIndex) {
200
+ return colIndex;
201
+ }
202
+ }
203
+ } else {
204
+ for (var _colIndex = 0; _colIndex < width; _colIndex++) {
205
+ var currentCellMapIndex = htmlRowIndex * width + _colIndex;
206
+ var cellAboveMapIndex = (htmlRowIndex - 1) * width + _colIndex;
207
+ if (_colIndex > 0) {
208
+ if (map[currentCellMapIndex] !== map[currentCellMapIndex - 1] && map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
209
+ htmlColCount++;
210
+ }
211
+ } else {
212
+ if (map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
213
+ htmlColCount++;
214
+ }
215
+ }
216
+ if (htmlColCount - 1 === htmlColIndex) {
217
+ return _colIndex;
218
+ }
219
+ }
220
+ }
221
+ return 0;
222
+ };
223
+
224
+ // When first row has merged cells, our converted column index needs to be mapped.
225
+ export var getColumnIndexMappedToColumnIndexInFirstRow = function getColumnIndexMappedToColumnIndexInFirstRow(convertedColIndex, htmlRowIndex, tableMap) {
226
+ var width = tableMap.width;
227
+ var map = tableMap.map;
228
+ var mapColIndexToFistRowColIndex = [];
229
+ var htmlColCounFirstRow = 0;
230
+ var colSpan = 0;
231
+ if (htmlRowIndex === 0) {
232
+ return convertedColIndex;
233
+ }
234
+ for (var colIndex = 0; colIndex < width; colIndex++) {
235
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
236
+ if (colSpan > 0) {
237
+ htmlColCounFirstRow += colSpan;
238
+ colSpan = 0;
239
+ }
240
+ htmlColCounFirstRow++;
241
+ } else if (map[colIndex] === map[colIndex - 1]) {
242
+ colSpan++;
243
+ }
244
+ mapColIndexToFistRowColIndex[colIndex] = htmlColCounFirstRow - 1;
245
+ }
246
+ return mapColIndexToFistRowColIndex[convertedColIndex];
185
247
  };
@@ -3,7 +3,7 @@ export { findControlsHoverDecoration, createControlsHoverDecoration, createColum
3
3
  export { isIsolating, containsHeaderColumn, containsHeaderRow, checkIfHeaderColumnEnabled, checkIfHeaderRowEnabled, checkIfNumberColumnEnabled, isLayoutSupported, getTableWidth, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns, isTableNested, anyChildCellMergedAcrossRow, supportedHeaderRow } from './nodes';
4
4
  export { unwrapContentFromTable, removeTableFromFirstChild, removeTableFromLastChild, transformSliceToRemoveOpenTable, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell } from './paste';
5
5
  export { isCell, isCornerButton, isInsertRowButton, isColumnControlsDecorations, isTableControlsButton, isTableContainerOrWrapper, isRowControlsButton, isDragRowControlsButton, isDragColumnFloatingInsertDot, isDragRowFloatingInsertDot, isDragCornerButton, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, updateResizeHandles, isResizeHandleDecoration, hasResizeHandler } from './dom';
6
- export { getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames } from './column-controls';
6
+ export { convertHTMLCellIndexToColumnIndex, getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames, getColumnIndexMappedToColumnIndexInFirstRow } from './column-controls';
7
7
  export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getRowsParams, getRowClassNames, copyPreviousRow } from './row-controls';
8
8
  export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
9
9
  export { getMergedCellsPositions } from './table';
@@ -1,5 +1,6 @@
1
1
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
2
2
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ import { TableMap } from '@atlaskit/editor-tables/table-map';
3
4
  export declare const getColumnsWidths: (view: EditorView) => Array<number | undefined>;
4
5
  export declare const isColumnDeleteButtonVisible: (selection: Selection) => boolean;
5
6
  export declare const getColumnDeleteButtonParams: (columnsWidths: Array<number | undefined>, selection: Selection) => {
@@ -8,3 +9,5 @@ export declare const getColumnDeleteButtonParams: (columnsWidths: Array<number |
8
9
  } | null;
9
10
  export declare const getColumnClassNames: (index: number, selection: Selection, hoveredColumns?: number[], isInDanger?: boolean, isResizing?: boolean) => string;
10
11
  export declare const colWidthsForRow: (tr: HTMLTableRowElement) => string;
12
+ export declare const convertHTMLCellIndexToColumnIndex: (htmlColIndex: number, htmlRowIndex: number, tableMap: TableMap) => number;
13
+ export declare const getColumnIndexMappedToColumnIndexInFirstRow: (convertedColIndex: number, htmlRowIndex: number, tableMap: TableMap) => number;
@@ -3,7 +3,7 @@ export { findControlsHoverDecoration, createControlsHoverDecoration, createColum
3
3
  export { isIsolating, containsHeaderColumn, containsHeaderRow, checkIfHeaderColumnEnabled, checkIfHeaderRowEnabled, checkIfNumberColumnEnabled, isLayoutSupported, getTableWidth, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns, isTableNested, anyChildCellMergedAcrossRow, supportedHeaderRow, } from './nodes';
4
4
  export { unwrapContentFromTable, removeTableFromFirstChild, removeTableFromLastChild, transformSliceToRemoveOpenTable, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, } from './paste';
5
5
  export { isCell, isCornerButton, isInsertRowButton, isColumnControlsDecorations, isTableControlsButton, isTableContainerOrWrapper, isRowControlsButton, isDragRowControlsButton, isDragColumnFloatingInsertDot, isDragRowFloatingInsertDot, isDragCornerButton, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, updateResizeHandles, isResizeHandleDecoration, hasResizeHandler, } from './dom';
6
- export { getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames, } from './column-controls';
6
+ export { convertHTMLCellIndexToColumnIndex, getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames, getColumnIndexMappedToColumnIndexInFirstRow, } from './column-controls';
7
7
  export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getRowsParams, getRowClassNames, copyPreviousRow, } from './row-controls';
8
8
  export type { RowParams } from './row-controls';
9
9
  export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
@@ -1,5 +1,6 @@
1
1
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
2
2
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
+ import { TableMap } from '@atlaskit/editor-tables/table-map';
3
4
  export declare const getColumnsWidths: (view: EditorView) => Array<number | undefined>;
4
5
  export declare const isColumnDeleteButtonVisible: (selection: Selection) => boolean;
5
6
  export declare const getColumnDeleteButtonParams: (columnsWidths: Array<number | undefined>, selection: Selection) => {
@@ -8,3 +9,5 @@ export declare const getColumnDeleteButtonParams: (columnsWidths: Array<number |
8
9
  } | null;
9
10
  export declare const getColumnClassNames: (index: number, selection: Selection, hoveredColumns?: number[], isInDanger?: boolean, isResizing?: boolean) => string;
10
11
  export declare const colWidthsForRow: (tr: HTMLTableRowElement) => string;
12
+ export declare const convertHTMLCellIndexToColumnIndex: (htmlColIndex: number, htmlRowIndex: number, tableMap: TableMap) => number;
13
+ export declare const getColumnIndexMappedToColumnIndexInFirstRow: (convertedColIndex: number, htmlRowIndex: number, tableMap: TableMap) => number;
@@ -3,7 +3,7 @@ export { findControlsHoverDecoration, createControlsHoverDecoration, createColum
3
3
  export { isIsolating, containsHeaderColumn, containsHeaderRow, checkIfHeaderColumnEnabled, checkIfHeaderRowEnabled, checkIfNumberColumnEnabled, isLayoutSupported, getTableWidth, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns, isTableNested, anyChildCellMergedAcrossRow, supportedHeaderRow, } from './nodes';
4
4
  export { unwrapContentFromTable, removeTableFromFirstChild, removeTableFromLastChild, transformSliceToRemoveOpenTable, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, } from './paste';
5
5
  export { isCell, isCornerButton, isInsertRowButton, isColumnControlsDecorations, isTableControlsButton, isTableContainerOrWrapper, isRowControlsButton, isDragRowControlsButton, isDragColumnFloatingInsertDot, isDragRowFloatingInsertDot, isDragCornerButton, getColumnOrRowIndex, getMousePositionHorizontalRelativeByElement, getMousePositionVerticalRelativeByElement, updateResizeHandles, isResizeHandleDecoration, hasResizeHandler, } from './dom';
6
- export { getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames, } from './column-controls';
6
+ export { convertHTMLCellIndexToColumnIndex, getColumnsWidths, isColumnDeleteButtonVisible, getColumnDeleteButtonParams, getColumnClassNames, getColumnIndexMappedToColumnIndexInFirstRow, } from './column-controls';
7
7
  export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getRowsParams, getRowClassNames, copyPreviousRow, } from './row-controls';
8
8
  export type { RowParams } from './row-controls';
9
9
  export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "5.4.12",
3
+ "version": "5.4.13",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -29,7 +29,7 @@
29
29
  "dependencies": {
30
30
  "@atlaskit/adf-schema": "^35.0.0",
31
31
  "@atlaskit/custom-steps": "^0.0.6",
32
- "@atlaskit/editor-common": "^76.24.0",
32
+ "@atlaskit/editor-common": "^76.25.0",
33
33
  "@atlaskit/editor-palette": "1.5.2",
34
34
  "@atlaskit/editor-plugin-analytics": "^0.3.0",
35
35
  "@atlaskit/editor-plugin-content-insertion": "^0.1.0",
@@ -1,4 +1,10 @@
1
- import { colWidthsForRow } from '../../../plugins/table/utils/column-controls';
1
+ import type { TableMap } from '@atlaskit/editor-tables';
2
+
3
+ import {
4
+ colWidthsForRow,
5
+ convertHTMLCellIndexToColumnIndex,
6
+ getColumnIndexMappedToColumnIndexInFirstRow,
7
+ } from '../../../plugins/table/utils/column-controls';
2
8
 
3
9
  const createRow = (colCount: number, childType = 'td') => {
4
10
  const tr = document.createElement('tr');
@@ -59,3 +65,141 @@ describe('table utilities', () => {
59
65
  });
60
66
  });
61
67
  });
68
+
69
+ describe('table utilities - convertHTMLCellIndexToColumnIndex', () => {
70
+ /*
71
+ Table looks like this:
72
+ ___ _______ ___ ___ ___
73
+ |___| |_A_|___|___|
74
+ |___| |___| |___|
75
+ |___|_______|_B_| |___|
76
+ |___|___|___|___| |___|
77
+ |___________|___|___|___|
78
+ |___________|___|_C_|___|
79
+ |___________|___|___|___|
80
+ |___|___|___|_D_|___|___|
81
+ |___|___|_E_____________|
82
+ */
83
+ const tableMap = {
84
+ width: 6,
85
+ height: 9,
86
+ map: [
87
+ 1, 5, 5, 9, 13, 17, 23, 5, 5, 27, 31, 35, 41, 5, 5, 45, 31, 49, 55, 59,
88
+ 63, 67, 31, 71, 77, 77, 77, 81, 31, 85, 91, 91, 91, 95, 99, 103, 109, 109,
89
+ 109, 113, 117, 121, 127, 131, 135, 139, 143, 147, 153, 157, 161, 161, 161,
90
+ 161,
91
+ ],
92
+ } as TableMap;
93
+
94
+ const testCases = [
95
+ [
96
+ 'case A: when hovered cell is in the first row and first row has merged cells',
97
+ 2, // htmlColIndex
98
+ 0, // htmlRowIndex
99
+ 3, // expected
100
+ ],
101
+ [
102
+ 'case B: when hoverd cell is not in the first row, but the row has merged cells',
103
+ 1,
104
+ 2,
105
+ 3,
106
+ ],
107
+ [
108
+ 'case C: when a cell that is in the row above and to the left of current cell is merged',
109
+ 3,
110
+ 5,
111
+ 5,
112
+ ],
113
+ [
114
+ 'case D: when first row has merged cell and hovered cell is below merged area',
115
+ 2,
116
+ 7,
117
+ 2,
118
+ ],
119
+ [
120
+ 'case E: when first row has merged cell and hovered cell is below merged area and is part of merged area',
121
+ 2,
122
+ 8,
123
+ 2,
124
+ ],
125
+ ];
126
+
127
+ describe('should convert cellIndex into colIndex correctly', () => {
128
+ test.each(testCases)(
129
+ '%s',
130
+ (message, htmlColIndex, htmlRowIndex, expected) => {
131
+ expect(
132
+ convertHTMLCellIndexToColumnIndex(
133
+ htmlColIndex as number,
134
+ htmlRowIndex as number,
135
+ tableMap,
136
+ ),
137
+ ).toEqual(expected);
138
+ },
139
+ );
140
+ });
141
+ });
142
+
143
+ describe('tableUtilities - getColumnIndexMappedToColumnIndexInFirstRow', () => {
144
+ /*
145
+ Table used for this tests looks like this:
146
+ ___ _______ ___ ___ ___ ___ ___ ___________ ___
147
+ |___|_______|___|___|___|___|___|___________|_D_|
148
+ |___|_A_|_B_|___|___|___|___|___|___|_E_|___|___|
149
+ |___|___|_______|___|_____C_|___|___|___|___|___|
150
+ |___|___|___|___|___|___|___|___|___|___|___|___|
151
+ */
152
+
153
+ const tableMap = {
154
+ width: 12,
155
+ height: 4,
156
+ map: [
157
+ 1, 5, 5, 9, 13, 17, 21, 25, 29, 29, 29, 33, 39, 43, 47, 51, 55, 59, 63,
158
+ 67, 71, 75, 79, 83, 89, 93, 97, 97, 101, 105, 105, 109, 113, 117, 121,
159
+ 125, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175,
160
+ ],
161
+ } as TableMap;
162
+
163
+ const testCases = [
164
+ [
165
+ 'case A: mouse is on a cell located below merged area of the first row closer to its start',
166
+ 2, // convertedColIndex
167
+ 1, // htmlRowIndex
168
+ 1, // expected
169
+ ],
170
+ [
171
+ 'case B: mouse is on a cell located below merged area of the first row close to its end',
172
+ 1,
173
+ 1,
174
+ 1,
175
+ ],
176
+ [
177
+ 'case E: mouse is on a cell located below merged area of the first row in the middle of the merged area',
178
+ 9,
179
+ 1,
180
+ 8,
181
+ ],
182
+ ['case C: mouse is on a merged cell located below the first row', 5, 2, 5],
183
+ [
184
+ 'case D: mouse is on a cell in the first row that is next to a merged cell',
185
+ 11,
186
+ 1,
187
+ 11,
188
+ ],
189
+ ];
190
+
191
+ describe('should adapt converted colIndex when first row has merged cells', () => {
192
+ test.each(testCases)(
193
+ '%s',
194
+ (message, convertedColIndex, htmlRowIndex, expected) => {
195
+ expect(
196
+ getColumnIndexMappedToColumnIndexInFirstRow(
197
+ convertedColIndex as number,
198
+ htmlRowIndex as number,
199
+ tableMap,
200
+ ),
201
+ ).toEqual(expected);
202
+ },
203
+ );
204
+ });
205
+ });
@@ -48,6 +48,8 @@ import { deleteColumns, deleteRows } from './transforms';
48
48
  import type { ElementContentRects } from './types';
49
49
  import { RESIZE_HANDLE_AREA_DECORATION_GAP } from './types';
50
50
  import {
51
+ convertHTMLCellIndexToColumnIndex,
52
+ getColumnIndexMappedToColumnIndexInFirstRow,
51
53
  getColumnOrRowIndex,
52
54
  getMousePositionHorizontalRelativeByElement,
53
55
  getMousePositionVerticalRelativeByElement,
@@ -552,24 +554,40 @@ const trackCellLocation = (view: EditorView, mouseEvent: Event) => {
552
554
  return;
553
555
  }
554
556
 
555
- const colIndex = maybeTableCell.cellIndex;
557
+ const htmlColIndex = maybeTableCell.cellIndex;
556
558
  const rowElement = closestElement(
557
559
  target as HTMLElement,
558
560
  'tr',
559
561
  ) as HTMLTableRowElement;
560
- const rowIndex = rowElement && rowElement.rowIndex;
562
+ const htmlRowIndex = rowElement && rowElement.rowIndex;
561
563
 
562
564
  const colHeight = tableRef.offsetHeight;
563
565
  const colWidth = maybeTableCell.offsetWidth;
564
566
 
567
+ const tableMap = tableNode && TableMap.get(tableNode);
568
+ let colIndex = htmlColIndex;
569
+ if (tableMap) {
570
+ const convertedColIndex = convertHTMLCellIndexToColumnIndex(
571
+ htmlColIndex,
572
+ htmlRowIndex,
573
+ tableMap,
574
+ );
575
+
576
+ colIndex = getColumnIndexMappedToColumnIndexInFirstRow(
577
+ convertedColIndex,
578
+ htmlRowIndex,
579
+ tableMap,
580
+ );
581
+ }
582
+
565
583
  if (
566
584
  hoveredCell.colIndex !== colIndex ||
567
- hoveredCell.rowIndex !== rowIndex ||
585
+ hoveredCell.rowIndex !== htmlRowIndex ||
568
586
  hoveredCell.colWidth !== colWidth ||
569
587
  hoveredCell.colHeight !== colHeight
570
588
  ) {
571
589
  hoverCell(
572
- rowIndex,
590
+ htmlRowIndex,
573
591
  colIndex,
574
592
  colWidth,
575
593
  colHeight,
@@ -217,3 +217,84 @@ export const colWidthsForRow = (tr: HTMLTableRowElement) => {
217
217
 
218
218
  return pctWidths.map((pct) => `${pct}%`).join(' ');
219
219
  };
220
+
221
+ export const convertHTMLCellIndexToColumnIndex = (
222
+ htmlColIndex: number,
223
+ htmlRowIndex: number,
224
+ tableMap: TableMap,
225
+ ): number => {
226
+ // Same numbers (positions) in tableMap.map array mean that there are merged cells.
227
+ // Cells can be merged across columns. So we need to check if the cell on the left and current cell have the same value.
228
+ // Cells can be merged acroll rows. So we need to check if the cell above has the same value as current cell.
229
+ // When cell has the same value as the cell above it or the cell to the left of it, html cellIndex won't count it a separete column.
230
+ const width = tableMap.width;
231
+ const map = tableMap.map;
232
+ let htmlColCount = 0;
233
+
234
+ if (htmlRowIndex === 0) {
235
+ for (let colIndex = 0; colIndex < width; colIndex++) {
236
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
237
+ htmlColCount++;
238
+ }
239
+
240
+ if (htmlColCount - 1 === htmlColIndex) {
241
+ return colIndex;
242
+ }
243
+ }
244
+ } else {
245
+ for (let colIndex = 0; colIndex < width; colIndex++) {
246
+ const currentCellMapIndex = htmlRowIndex * width + colIndex;
247
+ const cellAboveMapIndex = (htmlRowIndex - 1) * width + colIndex;
248
+ if (colIndex > 0) {
249
+ if (
250
+ map[currentCellMapIndex] !== map[currentCellMapIndex - 1] &&
251
+ map[currentCellMapIndex] !== map[cellAboveMapIndex]
252
+ ) {
253
+ htmlColCount++;
254
+ }
255
+ } else {
256
+ if (map[currentCellMapIndex] !== map[cellAboveMapIndex]) {
257
+ htmlColCount++;
258
+ }
259
+ }
260
+
261
+ if (htmlColCount - 1 === htmlColIndex) {
262
+ return colIndex;
263
+ }
264
+ }
265
+ }
266
+
267
+ return 0;
268
+ };
269
+
270
+ // When first row has merged cells, our converted column index needs to be mapped.
271
+ export const getColumnIndexMappedToColumnIndexInFirstRow = (
272
+ convertedColIndex: number,
273
+ htmlRowIndex: number,
274
+ tableMap: TableMap,
275
+ ): number => {
276
+ const width = tableMap.width;
277
+ const map = tableMap.map;
278
+ const mapColIndexToFistRowColIndex = [];
279
+ let htmlColCounFirstRow = 0;
280
+ let colSpan = 0;
281
+
282
+ if (htmlRowIndex === 0) {
283
+ return convertedColIndex;
284
+ }
285
+
286
+ for (let colIndex = 0; colIndex < width; colIndex++) {
287
+ if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) {
288
+ if (colSpan > 0) {
289
+ htmlColCounFirstRow += colSpan;
290
+ colSpan = 0;
291
+ }
292
+ htmlColCounFirstRow++;
293
+ } else if (map[colIndex] === map[colIndex - 1]) {
294
+ colSpan++;
295
+ }
296
+ mapColIndexToFistRowColIndex[colIndex] = htmlColCounFirstRow - 1;
297
+ }
298
+
299
+ return mapColIndexToFistRowColIndex[convertedColIndex];
300
+ };
@@ -59,10 +59,12 @@ export {
59
59
  hasResizeHandler,
60
60
  } from './dom';
61
61
  export {
62
+ convertHTMLCellIndexToColumnIndex,
62
63
  getColumnsWidths,
63
64
  isColumnDeleteButtonVisible,
64
65
  getColumnDeleteButtonParams,
65
66
  getColumnClassNames,
67
+ getColumnIndexMappedToColumnIndexInFirstRow,
66
68
  } from './column-controls';
67
69
  export {
68
70
  getRowHeights,
@@ -1,165 +0,0 @@
1
- export {};
2
- it.todo('TODO: ED-15801 - Fix smart link async rendering integration test');
3
- // import { runBlockNodeSelectionTestSuite } from '@atlaskit/editor-test-helpers/integration/selection';
4
- //
5
- // runBlockNodeSelectionTestSuite({
6
- // nodeName: 'table',
7
- // editorOptions: {
8
- // allowTables: {
9
- // advanced: true,
10
- // },
11
- // },
12
- // selector: 'table',
13
- // adfNode: {
14
- // type: 'table',
15
- // attrs: {
16
- // isNumberColumnEnabled: false,
17
- // layout: 'default',
18
- // localId: '15804638-b946-4591-b64c-beffe5122733',
19
- // },
20
- // content: [
21
- // {
22
- // type: 'tableRow',
23
- // content: [
24
- // {
25
- // type: 'tableHeader',
26
- // attrs: {},
27
- // content: [
28
- // {
29
- // type: 'paragraph',
30
- // content: [],
31
- // },
32
- // ],
33
- // },
34
- // {
35
- // type: 'tableHeader',
36
- // attrs: {},
37
- // content: [
38
- // {
39
- // type: 'paragraph',
40
- // content: [],
41
- // },
42
- // ],
43
- // },
44
- // {
45
- // type: 'tableHeader',
46
- // attrs: {},
47
- // content: [
48
- // {
49
- // type: 'paragraph',
50
- // content: [],
51
- // },
52
- // ],
53
- // },
54
- // ],
55
- // },
56
- // {
57
- // type: 'tableRow',
58
- // content: [
59
- // {
60
- // type: 'tableCell',
61
- // attrs: {},
62
- // content: [
63
- // {
64
- // type: 'paragraph',
65
- // content: [],
66
- // },
67
- // ],
68
- // },
69
- // {
70
- // type: 'tableCell',
71
- // attrs: {},
72
- // content: [
73
- // {
74
- // type: 'paragraph',
75
- // content: [],
76
- // },
77
- // ],
78
- // },
79
- // {
80
- // type: 'tableCell',
81
- // attrs: {},
82
- // content: [
83
- // {
84
- // type: 'paragraph',
85
- // content: [],
86
- // },
87
- // ],
88
- // },
89
- // ],
90
- // },
91
- // {
92
- // type: 'tableRow',
93
- // content: [
94
- // {
95
- // type: 'tableCell',
96
- // attrs: {},
97
- // content: [
98
- // {
99
- // type: 'paragraph',
100
- // content: [],
101
- // },
102
- // ],
103
- // },
104
- // {
105
- // type: 'tableCell',
106
- // attrs: {},
107
- // content: [
108
- // {
109
- // type: 'paragraph',
110
- // content: [],
111
- // },
112
- // ],
113
- // },
114
- // {
115
- // type: 'tableCell',
116
- // attrs: {},
117
- // content: [
118
- // {
119
- // type: 'paragraph',
120
- // content: [],
121
- // },
122
- // ],
123
- // },
124
- // ],
125
- // },
126
- // ],
127
- // },
128
- // skipTests: {
129
- // 'Extend selection right two characters to select [block-node] from line above with shift + arrow right': [
130
- // 'chrome',
131
- // 'safari',
132
- // 'firefox',
133
- // ],
134
- // 'Extend selection left two characters to select [block-node] from line below with shift + arrow left': [
135
- // 'chrome',
136
- // 'safari',
137
- // 'firefox',
138
- // ],
139
- // 'Extend a selection from end of the document to the start when [block-node] is the first node': [
140
- // 'chrome',
141
- // 'safari',
142
- // 'firefox',
143
- // ],
144
- // 'Click and drag from the end to start of the document to select [block-node] when [block-node] is the first node': [
145
- // 'chrome',
146
- // 'safari',
147
- // 'firefox',
148
- // ],
149
- // 'Extend a selection to the end of the document from start when [block-node] is the last node': [
150
- // 'chrome',
151
- // 'safari',
152
- // 'firefox',
153
- // ],
154
- // 'Click and drag from start of the document to select [block-node] when [block-node] is the last node': [
155
- // 'chrome',
156
- // 'safari',
157
- // 'firefox',
158
- // ],
159
- // "Extend selection down by one line multiple times to select [block-node]'s in sequence with shift + arrow down": [
160
- // 'chrome',
161
- // 'safari',
162
- // 'firefox',
163
- // ],
164
- // },
165
- // });