@atlaskit/editor-tables 2.3.17 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-tables
2
2
 
3
+ ## 2.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#67400](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/67400) [`191436e36f93`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/191436e36f93) - Optimised the table move row logic to perform insert/delete steps rather than an entire table replacement
8
+
9
+ ## 2.3.18
10
+
11
+ ### Patch Changes
12
+
13
+ - [#60278](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/60278) [`bc2785a02329`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/bc2785a02329) - Selection of multiple rows / column should remain when clicking the drag handle
14
+
3
15
  ## 2.3.17
4
16
 
5
17
  ### Patch Changes
@@ -7,10 +7,11 @@ exports.getSelectionRangeInRow = void 0;
7
7
  var _getCellsInColumn = require("./get-cells-in-column");
8
8
  var _getCellsInRow = require("./get-cells-in-row");
9
9
  // Returns a range of rectangular selection spanning all merged cells around a row at index `rowIndex`.
10
- var getSelectionRangeInRow = exports.getSelectionRangeInRow = function getSelectionRangeInRow(rowIndex) {
10
+ var getSelectionRangeInRow = exports.getSelectionRangeInRow = function getSelectionRangeInRow(startRowIndex) {
11
+ var endRowIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : startRowIndex;
11
12
  return function (tr) {
12
- var startIndex = rowIndex;
13
- var endIndex = rowIndex;
13
+ var startIndex = startRowIndex;
14
+ var endIndex = endRowIndex;
14
15
 
15
16
  // looking for selection start row (startIndex)
16
17
  var _loop = function _loop(i) {
@@ -27,7 +28,7 @@ var getSelectionRangeInRow = exports.getSelectionRangeInRow = function getSelect
27
28
  });
28
29
  }
29
30
  };
30
- for (var i = rowIndex; i >= 0; i--) {
31
+ for (var i = startRowIndex; i >= 0; i--) {
31
32
  _loop(i);
32
33
  }
33
34
  // looking for selection end row (endIndex)
@@ -42,7 +43,7 @@ var getSelectionRangeInRow = exports.getSelectionRangeInRow = function getSelect
42
43
  });
43
44
  }
44
45
  };
45
- for (var _i = rowIndex; _i <= endIndex; _i++) {
46
+ for (var _i = startRowIndex; _i <= endIndex; _i++) {
46
47
  _loop2(_i);
47
48
  }
48
49
 
@@ -147,7 +147,10 @@ var moveColumn = exports.moveColumn = function moveColumn(originColumnIndex, tar
147
147
  if (!table) {
148
148
  return tr;
149
149
  }
150
- var originalColumnRanges = (0, _getSelectionRangeInColumn.getSelectionRangeInColumn)(originColumnIndex)(tr);
150
+ if (!Array.isArray(originColumnIndex)) {
151
+ originColumnIndex = [originColumnIndex];
152
+ }
153
+ var originalColumnRanges = (0, _getSelectionRangeInColumn.getSelectionRangeInColumn)(originColumnIndex[0])(tr);
151
154
  var targetColumnRanges = (0, _getSelectionRangeInColumn.getSelectionRangeInColumn)(targetColumnIndex)(tr);
152
155
  var indexesOriginColumn = (_originalColumnRanges = originalColumnRanges === null || originalColumnRanges === void 0 ? void 0 : originalColumnRanges.indexes) !== null && _originalColumnRanges !== void 0 ? _originalColumnRanges : [];
153
156
  var indexesTargetColumn = (_targetColumnRanges$i = targetColumnRanges === null || targetColumnRanges === void 0 ? void 0 : targetColumnRanges.indexes) !== null && _targetColumnRanges$i !== void 0 ? _targetColumnRanges$i : [];
@@ -155,7 +158,7 @@ var moveColumn = exports.moveColumn = function moveColumn(originColumnIndex, tar
155
158
  return tr;
156
159
  }
157
160
  if (!options.tryToFit && indexesTargetColumn.length > 1) {
158
- (0, _reorderUtils.isValidReorder)(originColumnIndex, targetColumnIndex, indexesTargetColumn, 'column');
161
+ (0, _reorderUtils.isValidReorder)(originColumnIndex[0], targetColumnIndex, indexesTargetColumn, 'column');
159
162
  }
160
163
  var newTable = (0, _reorderUtils.moveTableColumn)(table, indexesOriginColumn, indexesTargetColumn, options.direction);
161
164
  var newTr = (0, _cloneTr.cloneTr)(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);
@@ -1,13 +1,17 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.moveRow = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _tableMap = require("../table-map");
7
11
  var _cloneTr = require("./clone-tr");
8
12
  var _find = require("./find");
9
13
  var _getSelectionRangeInRow = require("./get-selection-range-in-row");
10
- var _reorderUtils = require("./reorder-utils");
14
+ var _tableNodeTypes = require("./table-node-types");
11
15
  // :: (originRowIndex: number, targetRowIndex: targetColumnIndex, options?: MovementOptions) → (tr: Transaction) → Transaction
12
16
  // Returns a new transaction that moves the origin row to the target index;
13
17
  //
@@ -151,8 +155,8 @@ var _reorderUtils = require("./reorder-utils");
151
155
  // moveRow(x, y, options)(state.tr)
152
156
  // );
153
157
  // ```
154
- var moveRow = exports.moveRow = function moveRow(originRowIndex, targetRowIndex) {
155
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
158
+ var moveRow = exports.moveRow = function moveRow(state, originRowIndex, targetRowIndex) {
159
+ var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
156
160
  tryToFit: false,
157
161
  direction: 0
158
162
  };
@@ -161,18 +165,137 @@ var moveRow = exports.moveRow = function moveRow(originRowIndex, targetRowIndex)
161
165
  if (!table) {
162
166
  return tr;
163
167
  }
164
- var originalRowRanges = (0, _getSelectionRangeInRow.getSelectionRangeInRow)(originRowIndex)(tr);
168
+
169
+ // normalize the origin index to an array since move row support moving both a single & multiple rows in a single action.
170
+ if (!Array.isArray(originRowIndex)) {
171
+ originRowIndex = [originRowIndex];
172
+ }
173
+ if (originRowIndex.includes(targetRowIndex)) {
174
+ return tr;
175
+ }
176
+ var tableMap = _tableMap.TableMap.get(table.node);
177
+ var _originRowIndex$reduc = originRowIndex.reduce(function (_ref, cur) {
178
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
179
+ min = _ref2[0],
180
+ max = _ref2[1];
181
+ return [Math.min(min, cur), Math.max(max, cur)];
182
+ }, [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]),
183
+ _originRowIndex$reduc2 = (0, _slicedToArray2.default)(_originRowIndex$reduc, 2),
184
+ originMin = _originRowIndex$reduc2[0],
185
+ originMax = _originRowIndex$reduc2[1];
186
+ var originalRowRanges = (0, _getSelectionRangeInRow.getSelectionRangeInRow)(originMin, originMax)(tr);
165
187
  var targetRowRanges = (0, _getSelectionRangeInRow.getSelectionRangeInRow)(targetRowIndex)(tr);
166
188
  var indexesOriginRow = (originalRowRanges === null || originalRowRanges === void 0 ? void 0 : originalRowRanges.indexes) || [];
167
189
  var indexesTargetRow = (targetRowRanges === null || targetRowRanges === void 0 ? void 0 : targetRowRanges.indexes) || [];
168
- if (indexesOriginRow.includes(targetRowIndex)) {
190
+ if (originMin < 0 || originMin === Number.MAX_SAFE_INTEGER || originMax >= tableMap.height || originMax === Number.MIN_SAFE_INTEGER ||
191
+ // The target index cannot be within the origin bounds
192
+ targetRowIndex >= originMin && targetRowIndex <= originMax) {
169
193
  return tr;
170
194
  }
171
- if (!options.tryToFit && indexesTargetRow.length > 1) {
172
- (0, _reorderUtils.isValidReorder)(originRowIndex, targetRowIndex, indexesTargetRow, 'row');
195
+ var types = (0, _tableNodeTypes.tableNodeTypes)(state.schema);
196
+ var direction = normalizeDirection(originMin, targetRowIndex, options);
197
+ var actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'].apply(Math, (0, _toConsumableArray2.default)(indexesTargetRow));
198
+ var originPositions = indexesOriginRow.map(function (index) {
199
+ return tableMap.positionAt(index, 0, table.node) + table.pos;
200
+ });
201
+ var originNodes = originPositions.reduce(function (acc, pos) {
202
+ var node = tr.doc.nodeAt(tr.mapping.map(pos));
203
+ if (node) {
204
+ return [].concat((0, _toConsumableArray2.default)(acc), [{
205
+ pos: pos,
206
+ node: node
207
+ }]);
208
+ }
209
+ return acc;
210
+ }, []);
211
+ var targetPos = tableMap.positionAt(actualTargetIndex, 0, table.node) + table.pos;
212
+ var targetNode = tr.doc.nodeAt(tr.mapping.map(targetPos));
213
+ if (originNodes !== null && originNodes !== void 0 && originNodes.length && targetNode) {
214
+ var newTr = (0, _cloneTr.cloneTr)(tr);
215
+ var _determineTableHeader = determineTableHeaderState(table.node, tableMap, types),
216
+ rowHeaderEnabled = _determineTableHeader.rowHeaderEnabled,
217
+ columnHeaderEnabled = _determineTableHeader.columnHeaderEnabled;
218
+ if (rowHeaderEnabled && (originMin === 0 || actualTargetIndex === 0)) {
219
+ // This block is handling the situation where a row is moved in/out of the header position. If the header row option
220
+ // is enabled then;
221
+ // When a row is moved out, the row will be converted to a normal row and the row below it will become the header.
222
+ // When a row is moved in, the old row header needs to be made normal, and the incoming row needs to be made a header.
223
+ // This section only manages what happens to the other row, no the one being moved.
224
+ var nearHeaderPos = tableMap.positionAt(originMin === 0 ? originMax + 1 : actualTargetIndex, 0, table.node) + table.pos;
225
+ var nearHeaderNode = newTr.doc.nodeAt(newTr.mapping.map(nearHeaderPos));
226
+ if (nearHeaderNode) {
227
+ nearHeaderNode.forEach(function (node, offset, index) {
228
+ var start = newTr.mapping.map(nearHeaderPos + 1 + offset);
229
+ newTr.setNodeMarkup(start, actualTargetIndex !== 0 || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell, node.attrs);
230
+ });
231
+ }
232
+ }
233
+ var insertPos = direction === 'end' ? newTr.mapping.map(targetPos + targetNode.nodeSize, 1) : newTr.mapping.map(targetPos, -1);
234
+ newTr.insert(insertPos, originNodes.map(function (_ref3, index) {
235
+ var node = _ref3.node;
236
+ return normalizeRowNode(node, rowHeaderEnabled && actualTargetIndex === 0 && index === 0, columnHeaderEnabled, types);
237
+ }));
238
+ originNodes.forEach(function (_ref4) {
239
+ var pos = _ref4.pos,
240
+ node = _ref4.node;
241
+ newTr.delete(newTr.mapping.map(pos, 1), newTr.mapping.map(pos + node.nodeSize, -1));
242
+ });
243
+ return newTr;
173
244
  }
174
- var newTable = (0, _reorderUtils.moveTableRow)(table, indexesOriginRow, indexesTargetRow, options.direction);
175
- var newTr = (0, _cloneTr.cloneTr)(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);
176
- return newTr;
245
+ return tr;
177
246
  };
178
- };
247
+ };
248
+ function normalizeDirection(origin, target) {
249
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
250
+ tryToFit: false,
251
+ direction: 0
252
+ };
253
+ var dir = origin < target ? 'end' : 'start';
254
+ var override = options.direction < 0 ? 'start' : 'end';
255
+ return options.tryToFit && !!options.direction ? override : dir;
256
+ }
257
+ function determineTableHeaderState(table, tableMap, types) {
258
+ // We only really need to check the 2nd cell in the row/col if it's a header, since we only support a single full row/col header on the top & left
259
+ // of a table. We can assume that if the 2nd cell is a header then the entire row/col is a header.
260
+ // Be carefull though! when checking the 1st cell as it shares its header state with both row/cols.
261
+ // This means we wont be able to reliably identify header state on tables smaller the 2x2, however we can do best guess.
262
+
263
+ // This is a 3 bit mask;
264
+ // bit: 0 = Identifies if the cell at (0, 0) (row, col - 0-based) is a header cell or not
265
+ // bit: 1 = Identifies if the cell at (0, 1) is a header cell or not
266
+ // bit: 2 = Identifies if the cell at (1, 0) is a header cell or not
267
+ var mask = 0;
268
+
269
+ // At minimum we should have 1 cell in the table.
270
+ var topLeftCell = table.nodeAt(tableMap.map[0]);
271
+ // If this cell is a header that could indicate
272
+ mask |= topLeftCell && topLeftCell.type === types.header_cell ? 1 : 0;
273
+ if (tableMap.width > 1) {
274
+ var cell = table.nodeAt(tableMap.map[1]);
275
+ // If the cell at (0, 1) is a header then we set the bit flag to indicate row headers are enabled, otherwise if it's
276
+ // not then we will set the col headers enabled flag (and vice versa in the branch below) only if the cell at (0,0)
277
+ // was a header cell.
278
+ mask |= cell && cell.type === types.header_cell ? 2 : 4 * (mask & 1);
279
+ }
280
+ if (tableMap.height > 1) {
281
+ var _cell = table.nodeAt(tableMap.map[tableMap.width]);
282
+ mask |= _cell && _cell.type === types.header_cell ? 4 : 2 * (mask & 1);
283
+ }
284
+ return {
285
+ rowHeaderEnabled: mask === 7 || mask === 3,
286
+ columnHeaderEnabled: mask === 7 || mask === 5
287
+ };
288
+ }
289
+
290
+ /**
291
+ * This ensures the row node cell type correctly reflect what they should be.
292
+ * @returns A copy of the rowNode
293
+ */
294
+ function normalizeRowNode(rowNode, rowHeaderEnabled, columnHeaderEnabled, types) {
295
+ var content = [];
296
+ rowNode.forEach(function (node, offset, index) {
297
+ var newTargetType = rowHeaderEnabled || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell;
298
+ content.push(node.type !== newTargetType ? newTargetType.create(node.attrs, node.content, node.marks) : node);
299
+ });
300
+ return rowNode.type.create(rowNode.attrs, content, rowNode.marks);
301
+ }
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
- exports.selectTableClosestToPos = exports.selectTable = exports.selectRow = exports.selectColumn = void 0;
7
+ exports.selectTableClosestToPos = exports.selectTable = exports.selectRows = exports.selectRow = exports.selectColumns = exports.selectColumn = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
7
9
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
8
10
  var _cellSelection = require("../cell-selection");
9
11
  var _tableMap = require("../table-map");
@@ -115,6 +117,43 @@ var selectColumn = exports.selectColumn = select('column');
115
117
  // Returns a new transaction that selects a row at index `rowIndex`.
116
118
  // Use the optional `expand` param to extend from current selection.
117
119
  var selectRow = exports.selectRow = select('row');
120
+ var selectRowsOrColumns = function selectRowsOrColumns(type) {
121
+ return function (indexes) {
122
+ return function (tr) {
123
+ var table = (0, _find.findTable)(tr.selection);
124
+ if (!table) {
125
+ return tr;
126
+ }
127
+ var map = _tableMap.TableMap.get(table.node);
128
+ if (!indexes || indexes.length <= 0 || type === 'rows' && Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes)) > map.height || type === 'columns' && Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes)) > map.width || Math.min.apply(Math, (0, _toConsumableArray2.default)(indexes)) < 0) {
129
+ return tr;
130
+ }
131
+ var startCellRect = map.cellsInRect({
132
+ left: type === 'rows' ? 0 : Math.min.apply(Math, (0, _toConsumableArray2.default)(indexes)),
133
+ top: type === 'rows' ? Math.min.apply(Math, (0, _toConsumableArray2.default)(indexes)) : 0,
134
+ right: type === 'rows' ? map.width : Math.min.apply(Math, (0, _toConsumableArray2.default)(indexes)) + 1,
135
+ bottom: type === 'rows' ? Math.min.apply(Math, (0, _toConsumableArray2.default)(indexes)) + 1 : 1
136
+ });
137
+ var endCellRect = map.cellsInRect({
138
+ left: type === 'rows' ? map.width - 1 : Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes)),
139
+ top: type === 'rows' ? Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes)) : map.height - 1,
140
+ right: type === 'rows' ? map.width : Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes)) + 1,
141
+ bottom: type === 'rows' ? Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes)) + 1 : map.height
142
+ });
143
+ var head = table.start + startCellRect[0];
144
+ var anchor = table.start + endCellRect[endCellRect.length - 1];
145
+ var $head = tr.doc.resolve(head);
146
+ var $anchor = tr.doc.resolve(anchor);
147
+ return (0, _cloneTr.cloneTr)(tr.setSelection(new _cellSelection.CellSelection($anchor, $head)));
148
+ };
149
+ };
150
+ };
151
+
152
+ // Returns a new transaction that selects all rows at `indexes`.
153
+ var selectRows = exports.selectRows = selectRowsOrColumns('rows');
154
+
155
+ // Returns a new transaction that selects all columns at `indexes`.
156
+ var selectColumns = exports.selectColumns = selectRowsOrColumns('columns');
118
157
 
119
158
  // Returns a new transaction that selects a table.
120
159
  var selectTable = exports.selectTable = function selectTable(tr) {
package/dist/cjs/utils.js CHANGED
@@ -333,12 +333,24 @@ Object.defineProperty(exports, "selectColumn", {
333
333
  return _selectNodes.selectColumn;
334
334
  }
335
335
  });
336
+ Object.defineProperty(exports, "selectColumns", {
337
+ enumerable: true,
338
+ get: function get() {
339
+ return _selectNodes.selectColumns;
340
+ }
341
+ });
336
342
  Object.defineProperty(exports, "selectRow", {
337
343
  enumerable: true,
338
344
  get: function get() {
339
345
  return _selectNodes.selectRow;
340
346
  }
341
347
  });
348
+ Object.defineProperty(exports, "selectRows", {
349
+ enumerable: true,
350
+ get: function get() {
351
+ return _selectNodes.selectRows;
352
+ }
353
+ });
342
354
  Object.defineProperty(exports, "selectTable", {
343
355
  enumerable: true,
344
356
  get: function get() {
@@ -2,12 +2,12 @@ import { getCellsInColumn } from './get-cells-in-column';
2
2
  import { getCellsInRow } from './get-cells-in-row';
3
3
 
4
4
  // Returns a range of rectangular selection spanning all merged cells around a row at index `rowIndex`.
5
- export const getSelectionRangeInRow = rowIndex => tr => {
6
- let startIndex = rowIndex;
7
- let endIndex = rowIndex;
5
+ export const getSelectionRangeInRow = (startRowIndex, endRowIndex = startRowIndex) => tr => {
6
+ let startIndex = startRowIndex;
7
+ let endIndex = endRowIndex;
8
8
 
9
9
  // looking for selection start row (startIndex)
10
- for (let i = rowIndex; i >= 0; i--) {
10
+ for (let i = startRowIndex; i >= 0; i--) {
11
11
  const cells = getCellsInRow(i)(tr.selection);
12
12
  if (cells) {
13
13
  cells.forEach(cell => {
@@ -22,7 +22,7 @@ export const getSelectionRangeInRow = rowIndex => tr => {
22
22
  }
23
23
  }
24
24
  // looking for selection end row (endIndex)
25
- for (let i = rowIndex; i <= endIndex; i++) {
25
+ for (let i = startRowIndex; i <= endIndex; i++) {
26
26
  const cells = getCellsInRow(i)(tr.selection);
27
27
  if (cells) {
28
28
  cells.forEach(cell => {
@@ -140,7 +140,10 @@ export const moveColumn = (originColumnIndex, targetColumnIndex, options = {
140
140
  if (!table) {
141
141
  return tr;
142
142
  }
143
- const originalColumnRanges = getSelectionRangeInColumn(originColumnIndex)(tr);
143
+ if (!Array.isArray(originColumnIndex)) {
144
+ originColumnIndex = [originColumnIndex];
145
+ }
146
+ const originalColumnRanges = getSelectionRangeInColumn(originColumnIndex[0])(tr);
144
147
  const targetColumnRanges = getSelectionRangeInColumn(targetColumnIndex)(tr);
145
148
  const indexesOriginColumn = (_originalColumnRanges = originalColumnRanges === null || originalColumnRanges === void 0 ? void 0 : originalColumnRanges.indexes) !== null && _originalColumnRanges !== void 0 ? _originalColumnRanges : [];
146
149
  const indexesTargetColumn = (_targetColumnRanges$i = targetColumnRanges === null || targetColumnRanges === void 0 ? void 0 : targetColumnRanges.indexes) !== null && _targetColumnRanges$i !== void 0 ? _targetColumnRanges$i : [];
@@ -148,7 +151,7 @@ export const moveColumn = (originColumnIndex, targetColumnIndex, options = {
148
151
  return tr;
149
152
  }
150
153
  if (!options.tryToFit && indexesTargetColumn.length > 1) {
151
- isValidReorder(originColumnIndex, targetColumnIndex, indexesTargetColumn, 'column');
154
+ isValidReorder(originColumnIndex[0], targetColumnIndex, indexesTargetColumn, 'column');
152
155
  }
153
156
  const newTable = moveTableColumn(table, indexesOriginColumn, indexesTargetColumn, options.direction);
154
157
  const newTr = cloneTr(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);
@@ -1,7 +1,8 @@
1
+ import { TableMap } from '../table-map';
1
2
  import { cloneTr } from './clone-tr';
2
3
  import { findTable } from './find';
3
4
  import { getSelectionRangeInRow } from './get-selection-range-in-row';
4
- import { isValidReorder, moveTableRow } from './reorder-utils';
5
+ import { tableNodeTypes } from './table-node-types';
5
6
 
6
7
  // :: (originRowIndex: number, targetRowIndex: targetColumnIndex, options?: MovementOptions) → (tr: Transaction) → Transaction
7
8
  // Returns a new transaction that moves the origin row to the target index;
@@ -146,7 +147,7 @@ import { isValidReorder, moveTableRow } from './reorder-utils';
146
147
  // moveRow(x, y, options)(state.tr)
147
148
  // );
148
149
  // ```
149
- export const moveRow = (originRowIndex, targetRowIndex, options = {
150
+ export const moveRow = (state, originRowIndex, targetRowIndex, options = {
150
151
  tryToFit: false,
151
152
  direction: 0
152
153
  }) => tr => {
@@ -154,17 +155,126 @@ export const moveRow = (originRowIndex, targetRowIndex, options = {
154
155
  if (!table) {
155
156
  return tr;
156
157
  }
157
- const originalRowRanges = getSelectionRangeInRow(originRowIndex)(tr);
158
+
159
+ // normalize the origin index to an array since move row support moving both a single & multiple rows in a single action.
160
+ if (!Array.isArray(originRowIndex)) {
161
+ originRowIndex = [originRowIndex];
162
+ }
163
+ if (originRowIndex.includes(targetRowIndex)) {
164
+ return tr;
165
+ }
166
+ const tableMap = TableMap.get(table.node);
167
+ const [originMin, originMax] = originRowIndex.reduce(([min, max], cur) => [Math.min(min, cur), Math.max(max, cur)], [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]);
168
+ const originalRowRanges = getSelectionRangeInRow(originMin, originMax)(tr);
158
169
  const targetRowRanges = getSelectionRangeInRow(targetRowIndex)(tr);
159
170
  const indexesOriginRow = (originalRowRanges === null || originalRowRanges === void 0 ? void 0 : originalRowRanges.indexes) || [];
160
171
  const indexesTargetRow = (targetRowRanges === null || targetRowRanges === void 0 ? void 0 : targetRowRanges.indexes) || [];
161
- if (indexesOriginRow.includes(targetRowIndex)) {
172
+ if (originMin < 0 || originMin === Number.MAX_SAFE_INTEGER || originMax >= tableMap.height || originMax === Number.MIN_SAFE_INTEGER ||
173
+ // The target index cannot be within the origin bounds
174
+ targetRowIndex >= originMin && targetRowIndex <= originMax) {
162
175
  return tr;
163
176
  }
164
- if (!options.tryToFit && indexesTargetRow.length > 1) {
165
- isValidReorder(originRowIndex, targetRowIndex, indexesTargetRow, 'row');
177
+ const types = tableNodeTypes(state.schema);
178
+ const direction = normalizeDirection(originMin, targetRowIndex, options);
179
+ const actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'](...indexesTargetRow);
180
+ const originPositions = indexesOriginRow.map(index => tableMap.positionAt(index, 0, table.node) + table.pos);
181
+ const originNodes = originPositions.reduce((acc, pos) => {
182
+ const node = tr.doc.nodeAt(tr.mapping.map(pos));
183
+ if (node) {
184
+ return [...acc, {
185
+ pos,
186
+ node
187
+ }];
188
+ }
189
+ return acc;
190
+ }, []);
191
+ const targetPos = tableMap.positionAt(actualTargetIndex, 0, table.node) + table.pos;
192
+ const targetNode = tr.doc.nodeAt(tr.mapping.map(targetPos));
193
+ if (originNodes !== null && originNodes !== void 0 && originNodes.length && targetNode) {
194
+ const newTr = cloneTr(tr);
195
+ const {
196
+ rowHeaderEnabled,
197
+ columnHeaderEnabled
198
+ } = determineTableHeaderState(table.node, tableMap, types);
199
+ if (rowHeaderEnabled && (originMin === 0 || actualTargetIndex === 0)) {
200
+ // This block is handling the situation where a row is moved in/out of the header position. If the header row option
201
+ // is enabled then;
202
+ // When a row is moved out, the row will be converted to a normal row and the row below it will become the header.
203
+ // When a row is moved in, the old row header needs to be made normal, and the incoming row needs to be made a header.
204
+ // This section only manages what happens to the other row, no the one being moved.
205
+ const nearHeaderPos = tableMap.positionAt(originMin === 0 ? originMax + 1 : actualTargetIndex, 0, table.node) + table.pos;
206
+ const nearHeaderNode = newTr.doc.nodeAt(newTr.mapping.map(nearHeaderPos));
207
+ if (nearHeaderNode) {
208
+ nearHeaderNode.forEach((node, offset, index) => {
209
+ const start = newTr.mapping.map(nearHeaderPos + 1 + offset);
210
+ newTr.setNodeMarkup(start, actualTargetIndex !== 0 || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell, node.attrs);
211
+ });
212
+ }
213
+ }
214
+ const insertPos = direction === 'end' ? newTr.mapping.map(targetPos + targetNode.nodeSize, 1) : newTr.mapping.map(targetPos, -1);
215
+ newTr.insert(insertPos, originNodes.map(({
216
+ node
217
+ }, index) => normalizeRowNode(node, rowHeaderEnabled && actualTargetIndex === 0 && index === 0, columnHeaderEnabled, types)));
218
+ originNodes.forEach(({
219
+ pos,
220
+ node
221
+ }) => {
222
+ newTr.delete(newTr.mapping.map(pos, 1), newTr.mapping.map(pos + node.nodeSize, -1));
223
+ });
224
+ return newTr;
166
225
  }
167
- const newTable = moveTableRow(table, indexesOriginRow, indexesTargetRow, options.direction);
168
- const newTr = cloneTr(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);
169
- return newTr;
170
- };
226
+ return tr;
227
+ };
228
+ function normalizeDirection(origin, target, options = {
229
+ tryToFit: false,
230
+ direction: 0
231
+ }) {
232
+ const dir = origin < target ? 'end' : 'start';
233
+ const override = options.direction < 0 ? 'start' : 'end';
234
+ return options.tryToFit && !!options.direction ? override : dir;
235
+ }
236
+ function determineTableHeaderState(table, tableMap, types) {
237
+ // We only really need to check the 2nd cell in the row/col if it's a header, since we only support a single full row/col header on the top & left
238
+ // of a table. We can assume that if the 2nd cell is a header then the entire row/col is a header.
239
+ // Be carefull though! when checking the 1st cell as it shares its header state with both row/cols.
240
+ // This means we wont be able to reliably identify header state on tables smaller the 2x2, however we can do best guess.
241
+
242
+ // This is a 3 bit mask;
243
+ // bit: 0 = Identifies if the cell at (0, 0) (row, col - 0-based) is a header cell or not
244
+ // bit: 1 = Identifies if the cell at (0, 1) is a header cell or not
245
+ // bit: 2 = Identifies if the cell at (1, 0) is a header cell or not
246
+ let mask = 0;
247
+
248
+ // At minimum we should have 1 cell in the table.
249
+ const topLeftCell = table.nodeAt(tableMap.map[0]);
250
+ // If this cell is a header that could indicate
251
+ mask |= topLeftCell && topLeftCell.type === types.header_cell ? 1 : 0;
252
+ if (tableMap.width > 1) {
253
+ const cell = table.nodeAt(tableMap.map[1]);
254
+ // If the cell at (0, 1) is a header then we set the bit flag to indicate row headers are enabled, otherwise if it's
255
+ // not then we will set the col headers enabled flag (and vice versa in the branch below) only if the cell at (0,0)
256
+ // was a header cell.
257
+ mask |= cell && cell.type === types.header_cell ? 2 : 4 * (mask & 1);
258
+ }
259
+ if (tableMap.height > 1) {
260
+ const cell = table.nodeAt(tableMap.map[tableMap.width]);
261
+ mask |= cell && cell.type === types.header_cell ? 4 : 2 * (mask & 1);
262
+ }
263
+ return {
264
+ rowHeaderEnabled: mask === 7 || mask === 3,
265
+ columnHeaderEnabled: mask === 7 || mask === 5
266
+ };
267
+ }
268
+
269
+ /**
270
+ * This ensures the row node cell type correctly reflect what they should be.
271
+ * @returns A copy of the rowNode
272
+ */
273
+ function normalizeRowNode(rowNode, rowHeaderEnabled, columnHeaderEnabled, types) {
274
+ let content = [];
275
+ rowNode.forEach((node, offset, index) => {
276
+ const newTargetType = rowHeaderEnabled || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell;
277
+ content.push(node.type !== newTargetType ? newTargetType.create(node.attrs, node.content, node.marks) : node);
278
+ });
279
+ return rowNode.type.create(rowNode.attrs, content, rowNode.marks);
280
+ }
@@ -105,6 +105,39 @@ export const selectColumn = select('column');
105
105
  // Returns a new transaction that selects a row at index `rowIndex`.
106
106
  // Use the optional `expand` param to extend from current selection.
107
107
  export const selectRow = select('row');
108
+ const selectRowsOrColumns = type => indexes => tr => {
109
+ const table = findTable(tr.selection);
110
+ if (!table) {
111
+ return tr;
112
+ }
113
+ const map = TableMap.get(table.node);
114
+ if (!indexes || indexes.length <= 0 || type === 'rows' && Math.max(...indexes) > map.height || type === 'columns' && Math.max(...indexes) > map.width || Math.min(...indexes) < 0) {
115
+ return tr;
116
+ }
117
+ const startCellRect = map.cellsInRect({
118
+ left: type === 'rows' ? 0 : Math.min(...indexes),
119
+ top: type === 'rows' ? Math.min(...indexes) : 0,
120
+ right: type === 'rows' ? map.width : Math.min(...indexes) + 1,
121
+ bottom: type === 'rows' ? Math.min(...indexes) + 1 : 1
122
+ });
123
+ const endCellRect = map.cellsInRect({
124
+ left: type === 'rows' ? map.width - 1 : Math.max(...indexes),
125
+ top: type === 'rows' ? Math.max(...indexes) : map.height - 1,
126
+ right: type === 'rows' ? map.width : Math.max(...indexes) + 1,
127
+ bottom: type === 'rows' ? Math.max(...indexes) + 1 : map.height
128
+ });
129
+ const head = table.start + startCellRect[0];
130
+ const anchor = table.start + endCellRect[endCellRect.length - 1];
131
+ const $head = tr.doc.resolve(head);
132
+ const $anchor = tr.doc.resolve(anchor);
133
+ return cloneTr(tr.setSelection(new CellSelection($anchor, $head)));
134
+ };
135
+
136
+ // Returns a new transaction that selects all rows at `indexes`.
137
+ export const selectRows = selectRowsOrColumns('rows');
138
+
139
+ // Returns a new transaction that selects all columns at `indexes`.
140
+ export const selectColumns = selectRowsOrColumns('columns');
108
141
 
109
142
  // Returns a new transaction that selects a table.
110
143
  export const selectTable = tr => {
@@ -27,7 +27,7 @@ export { normalizeSelection } from './utils/normalize-selection';
27
27
  export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos } from './utils/remove-column';
28
28
  export { removeRowAt, removeSelectedRows, removeRowClosestToPos } from './utils/remove-row';
29
29
  export { removeTable } from './utils/remove-table';
30
- export { selectColumn, selectRow, selectTable } from './utils/select-nodes';
30
+ export { selectColumn, selectColumns, selectRow, selectRows, selectTable } from './utils/select-nodes';
31
31
  export { selectionCell } from './utils/selection-cell';
32
32
  export { selectedRect } from './utils/selection-rect';
33
33
  export { setCellAttrs } from './utils/set-cell-attrs';
@@ -2,10 +2,11 @@ import { getCellsInColumn } from './get-cells-in-column';
2
2
  import { getCellsInRow } from './get-cells-in-row';
3
3
 
4
4
  // Returns a range of rectangular selection spanning all merged cells around a row at index `rowIndex`.
5
- export var getSelectionRangeInRow = function getSelectionRangeInRow(rowIndex) {
5
+ export var getSelectionRangeInRow = function getSelectionRangeInRow(startRowIndex) {
6
+ var endRowIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : startRowIndex;
6
7
  return function (tr) {
7
- var startIndex = rowIndex;
8
- var endIndex = rowIndex;
8
+ var startIndex = startRowIndex;
9
+ var endIndex = endRowIndex;
9
10
 
10
11
  // looking for selection start row (startIndex)
11
12
  var _loop = function _loop(i) {
@@ -22,7 +23,7 @@ export var getSelectionRangeInRow = function getSelectionRangeInRow(rowIndex) {
22
23
  });
23
24
  }
24
25
  };
25
- for (var i = rowIndex; i >= 0; i--) {
26
+ for (var i = startRowIndex; i >= 0; i--) {
26
27
  _loop(i);
27
28
  }
28
29
  // looking for selection end row (endIndex)
@@ -37,7 +38,7 @@ export var getSelectionRangeInRow = function getSelectionRangeInRow(rowIndex) {
37
38
  });
38
39
  }
39
40
  };
40
- for (var _i = rowIndex; _i <= endIndex; _i++) {
41
+ for (var _i = startRowIndex; _i <= endIndex; _i++) {
41
42
  _loop2(_i);
42
43
  }
43
44
 
@@ -142,7 +142,10 @@ export var moveColumn = function moveColumn(originColumnIndex, targetColumnIndex
142
142
  if (!table) {
143
143
  return tr;
144
144
  }
145
- var originalColumnRanges = getSelectionRangeInColumn(originColumnIndex)(tr);
145
+ if (!Array.isArray(originColumnIndex)) {
146
+ originColumnIndex = [originColumnIndex];
147
+ }
148
+ var originalColumnRanges = getSelectionRangeInColumn(originColumnIndex[0])(tr);
146
149
  var targetColumnRanges = getSelectionRangeInColumn(targetColumnIndex)(tr);
147
150
  var indexesOriginColumn = (_originalColumnRanges = originalColumnRanges === null || originalColumnRanges === void 0 ? void 0 : originalColumnRanges.indexes) !== null && _originalColumnRanges !== void 0 ? _originalColumnRanges : [];
148
151
  var indexesTargetColumn = (_targetColumnRanges$i = targetColumnRanges === null || targetColumnRanges === void 0 ? void 0 : targetColumnRanges.indexes) !== null && _targetColumnRanges$i !== void 0 ? _targetColumnRanges$i : [];
@@ -150,7 +153,7 @@ export var moveColumn = function moveColumn(originColumnIndex, targetColumnIndex
150
153
  return tr;
151
154
  }
152
155
  if (!options.tryToFit && indexesTargetColumn.length > 1) {
153
- isValidReorder(originColumnIndex, targetColumnIndex, indexesTargetColumn, 'column');
156
+ isValidReorder(originColumnIndex[0], targetColumnIndex, indexesTargetColumn, 'column');
154
157
  }
155
158
  var newTable = moveTableColumn(table, indexesOriginColumn, indexesTargetColumn, options.direction);
156
159
  var newTr = cloneTr(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);
@@ -1,7 +1,10 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import { TableMap } from '../table-map';
1
4
  import { cloneTr } from './clone-tr';
2
5
  import { findTable } from './find';
3
6
  import { getSelectionRangeInRow } from './get-selection-range-in-row';
4
- import { isValidReorder, moveTableRow } from './reorder-utils';
7
+ import { tableNodeTypes } from './table-node-types';
5
8
 
6
9
  // :: (originRowIndex: number, targetRowIndex: targetColumnIndex, options?: MovementOptions) → (tr: Transaction) → Transaction
7
10
  // Returns a new transaction that moves the origin row to the target index;
@@ -146,8 +149,8 @@ import { isValidReorder, moveTableRow } from './reorder-utils';
146
149
  // moveRow(x, y, options)(state.tr)
147
150
  // );
148
151
  // ```
149
- export var moveRow = function moveRow(originRowIndex, targetRowIndex) {
150
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
152
+ export var moveRow = function moveRow(state, originRowIndex, targetRowIndex) {
153
+ var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
151
154
  tryToFit: false,
152
155
  direction: 0
153
156
  };
@@ -156,18 +159,137 @@ export var moveRow = function moveRow(originRowIndex, targetRowIndex) {
156
159
  if (!table) {
157
160
  return tr;
158
161
  }
159
- var originalRowRanges = getSelectionRangeInRow(originRowIndex)(tr);
162
+
163
+ // normalize the origin index to an array since move row support moving both a single & multiple rows in a single action.
164
+ if (!Array.isArray(originRowIndex)) {
165
+ originRowIndex = [originRowIndex];
166
+ }
167
+ if (originRowIndex.includes(targetRowIndex)) {
168
+ return tr;
169
+ }
170
+ var tableMap = TableMap.get(table.node);
171
+ var _originRowIndex$reduc = originRowIndex.reduce(function (_ref, cur) {
172
+ var _ref2 = _slicedToArray(_ref, 2),
173
+ min = _ref2[0],
174
+ max = _ref2[1];
175
+ return [Math.min(min, cur), Math.max(max, cur)];
176
+ }, [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]),
177
+ _originRowIndex$reduc2 = _slicedToArray(_originRowIndex$reduc, 2),
178
+ originMin = _originRowIndex$reduc2[0],
179
+ originMax = _originRowIndex$reduc2[1];
180
+ var originalRowRanges = getSelectionRangeInRow(originMin, originMax)(tr);
160
181
  var targetRowRanges = getSelectionRangeInRow(targetRowIndex)(tr);
161
182
  var indexesOriginRow = (originalRowRanges === null || originalRowRanges === void 0 ? void 0 : originalRowRanges.indexes) || [];
162
183
  var indexesTargetRow = (targetRowRanges === null || targetRowRanges === void 0 ? void 0 : targetRowRanges.indexes) || [];
163
- if (indexesOriginRow.includes(targetRowIndex)) {
184
+ if (originMin < 0 || originMin === Number.MAX_SAFE_INTEGER || originMax >= tableMap.height || originMax === Number.MIN_SAFE_INTEGER ||
185
+ // The target index cannot be within the origin bounds
186
+ targetRowIndex >= originMin && targetRowIndex <= originMax) {
164
187
  return tr;
165
188
  }
166
- if (!options.tryToFit && indexesTargetRow.length > 1) {
167
- isValidReorder(originRowIndex, targetRowIndex, indexesTargetRow, 'row');
189
+ var types = tableNodeTypes(state.schema);
190
+ var direction = normalizeDirection(originMin, targetRowIndex, options);
191
+ var actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'].apply(Math, _toConsumableArray(indexesTargetRow));
192
+ var originPositions = indexesOriginRow.map(function (index) {
193
+ return tableMap.positionAt(index, 0, table.node) + table.pos;
194
+ });
195
+ var originNodes = originPositions.reduce(function (acc, pos) {
196
+ var node = tr.doc.nodeAt(tr.mapping.map(pos));
197
+ if (node) {
198
+ return [].concat(_toConsumableArray(acc), [{
199
+ pos: pos,
200
+ node: node
201
+ }]);
202
+ }
203
+ return acc;
204
+ }, []);
205
+ var targetPos = tableMap.positionAt(actualTargetIndex, 0, table.node) + table.pos;
206
+ var targetNode = tr.doc.nodeAt(tr.mapping.map(targetPos));
207
+ if (originNodes !== null && originNodes !== void 0 && originNodes.length && targetNode) {
208
+ var newTr = cloneTr(tr);
209
+ var _determineTableHeader = determineTableHeaderState(table.node, tableMap, types),
210
+ rowHeaderEnabled = _determineTableHeader.rowHeaderEnabled,
211
+ columnHeaderEnabled = _determineTableHeader.columnHeaderEnabled;
212
+ if (rowHeaderEnabled && (originMin === 0 || actualTargetIndex === 0)) {
213
+ // This block is handling the situation where a row is moved in/out of the header position. If the header row option
214
+ // is enabled then;
215
+ // When a row is moved out, the row will be converted to a normal row and the row below it will become the header.
216
+ // When a row is moved in, the old row header needs to be made normal, and the incoming row needs to be made a header.
217
+ // This section only manages what happens to the other row, no the one being moved.
218
+ var nearHeaderPos = tableMap.positionAt(originMin === 0 ? originMax + 1 : actualTargetIndex, 0, table.node) + table.pos;
219
+ var nearHeaderNode = newTr.doc.nodeAt(newTr.mapping.map(nearHeaderPos));
220
+ if (nearHeaderNode) {
221
+ nearHeaderNode.forEach(function (node, offset, index) {
222
+ var start = newTr.mapping.map(nearHeaderPos + 1 + offset);
223
+ newTr.setNodeMarkup(start, actualTargetIndex !== 0 || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell, node.attrs);
224
+ });
225
+ }
226
+ }
227
+ var insertPos = direction === 'end' ? newTr.mapping.map(targetPos + targetNode.nodeSize, 1) : newTr.mapping.map(targetPos, -1);
228
+ newTr.insert(insertPos, originNodes.map(function (_ref3, index) {
229
+ var node = _ref3.node;
230
+ return normalizeRowNode(node, rowHeaderEnabled && actualTargetIndex === 0 && index === 0, columnHeaderEnabled, types);
231
+ }));
232
+ originNodes.forEach(function (_ref4) {
233
+ var pos = _ref4.pos,
234
+ node = _ref4.node;
235
+ newTr.delete(newTr.mapping.map(pos, 1), newTr.mapping.map(pos + node.nodeSize, -1));
236
+ });
237
+ return newTr;
168
238
  }
169
- var newTable = moveTableRow(table, indexesOriginRow, indexesTargetRow, options.direction);
170
- var newTr = cloneTr(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);
171
- return newTr;
239
+ return tr;
172
240
  };
173
- };
241
+ };
242
+ function normalizeDirection(origin, target) {
243
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
244
+ tryToFit: false,
245
+ direction: 0
246
+ };
247
+ var dir = origin < target ? 'end' : 'start';
248
+ var override = options.direction < 0 ? 'start' : 'end';
249
+ return options.tryToFit && !!options.direction ? override : dir;
250
+ }
251
+ function determineTableHeaderState(table, tableMap, types) {
252
+ // We only really need to check the 2nd cell in the row/col if it's a header, since we only support a single full row/col header on the top & left
253
+ // of a table. We can assume that if the 2nd cell is a header then the entire row/col is a header.
254
+ // Be carefull though! when checking the 1st cell as it shares its header state with both row/cols.
255
+ // This means we wont be able to reliably identify header state on tables smaller the 2x2, however we can do best guess.
256
+
257
+ // This is a 3 bit mask;
258
+ // bit: 0 = Identifies if the cell at (0, 0) (row, col - 0-based) is a header cell or not
259
+ // bit: 1 = Identifies if the cell at (0, 1) is a header cell or not
260
+ // bit: 2 = Identifies if the cell at (1, 0) is a header cell or not
261
+ var mask = 0;
262
+
263
+ // At minimum we should have 1 cell in the table.
264
+ var topLeftCell = table.nodeAt(tableMap.map[0]);
265
+ // If this cell is a header that could indicate
266
+ mask |= topLeftCell && topLeftCell.type === types.header_cell ? 1 : 0;
267
+ if (tableMap.width > 1) {
268
+ var cell = table.nodeAt(tableMap.map[1]);
269
+ // If the cell at (0, 1) is a header then we set the bit flag to indicate row headers are enabled, otherwise if it's
270
+ // not then we will set the col headers enabled flag (and vice versa in the branch below) only if the cell at (0,0)
271
+ // was a header cell.
272
+ mask |= cell && cell.type === types.header_cell ? 2 : 4 * (mask & 1);
273
+ }
274
+ if (tableMap.height > 1) {
275
+ var _cell = table.nodeAt(tableMap.map[tableMap.width]);
276
+ mask |= _cell && _cell.type === types.header_cell ? 4 : 2 * (mask & 1);
277
+ }
278
+ return {
279
+ rowHeaderEnabled: mask === 7 || mask === 3,
280
+ columnHeaderEnabled: mask === 7 || mask === 5
281
+ };
282
+ }
283
+
284
+ /**
285
+ * This ensures the row node cell type correctly reflect what they should be.
286
+ * @returns A copy of the rowNode
287
+ */
288
+ function normalizeRowNode(rowNode, rowHeaderEnabled, columnHeaderEnabled, types) {
289
+ var content = [];
290
+ rowNode.forEach(function (node, offset, index) {
291
+ var newTargetType = rowHeaderEnabled || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell;
292
+ content.push(node.type !== newTargetType ? newTargetType.create(node.attrs, node.content, node.marks) : node);
293
+ });
294
+ return rowNode.type.create(rowNode.attrs, content, rowNode.marks);
295
+ }
@@ -1,3 +1,4 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
2
3
  import { CellSelection } from '../cell-selection';
3
4
  import { TableMap } from '../table-map';
@@ -109,6 +110,43 @@ export var selectColumn = select('column');
109
110
  // Returns a new transaction that selects a row at index `rowIndex`.
110
111
  // Use the optional `expand` param to extend from current selection.
111
112
  export var selectRow = select('row');
113
+ var selectRowsOrColumns = function selectRowsOrColumns(type) {
114
+ return function (indexes) {
115
+ return function (tr) {
116
+ var table = findTable(tr.selection);
117
+ if (!table) {
118
+ return tr;
119
+ }
120
+ var map = TableMap.get(table.node);
121
+ if (!indexes || indexes.length <= 0 || type === 'rows' && Math.max.apply(Math, _toConsumableArray(indexes)) > map.height || type === 'columns' && Math.max.apply(Math, _toConsumableArray(indexes)) > map.width || Math.min.apply(Math, _toConsumableArray(indexes)) < 0) {
122
+ return tr;
123
+ }
124
+ var startCellRect = map.cellsInRect({
125
+ left: type === 'rows' ? 0 : Math.min.apply(Math, _toConsumableArray(indexes)),
126
+ top: type === 'rows' ? Math.min.apply(Math, _toConsumableArray(indexes)) : 0,
127
+ right: type === 'rows' ? map.width : Math.min.apply(Math, _toConsumableArray(indexes)) + 1,
128
+ bottom: type === 'rows' ? Math.min.apply(Math, _toConsumableArray(indexes)) + 1 : 1
129
+ });
130
+ var endCellRect = map.cellsInRect({
131
+ left: type === 'rows' ? map.width - 1 : Math.max.apply(Math, _toConsumableArray(indexes)),
132
+ top: type === 'rows' ? Math.max.apply(Math, _toConsumableArray(indexes)) : map.height - 1,
133
+ right: type === 'rows' ? map.width : Math.max.apply(Math, _toConsumableArray(indexes)) + 1,
134
+ bottom: type === 'rows' ? Math.max.apply(Math, _toConsumableArray(indexes)) + 1 : map.height
135
+ });
136
+ var head = table.start + startCellRect[0];
137
+ var anchor = table.start + endCellRect[endCellRect.length - 1];
138
+ var $head = tr.doc.resolve(head);
139
+ var $anchor = tr.doc.resolve(anchor);
140
+ return cloneTr(tr.setSelection(new CellSelection($anchor, $head)));
141
+ };
142
+ };
143
+ };
144
+
145
+ // Returns a new transaction that selects all rows at `indexes`.
146
+ export var selectRows = selectRowsOrColumns('rows');
147
+
148
+ // Returns a new transaction that selects all columns at `indexes`.
149
+ export var selectColumns = selectRowsOrColumns('columns');
112
150
 
113
151
  // Returns a new transaction that selects a table.
114
152
  export var selectTable = function selectTable(tr) {
package/dist/esm/utils.js CHANGED
@@ -27,7 +27,7 @@ export { normalizeSelection } from './utils/normalize-selection';
27
27
  export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos } from './utils/remove-column';
28
28
  export { removeRowAt, removeSelectedRows, removeRowClosestToPos } from './utils/remove-row';
29
29
  export { removeTable } from './utils/remove-table';
30
- export { selectColumn, selectRow, selectTable } from './utils/select-nodes';
30
+ export { selectColumn, selectColumns, selectRow, selectRows, selectTable } from './utils/select-nodes';
31
31
  export { selectionCell } from './utils/selection-cell';
32
32
  export { selectedRect } from './utils/selection-rect';
33
33
  export { setCellAttrs } from './utils/set-cell-attrs';
@@ -1,3 +1,3 @@
1
- import { Transaction } from '@atlaskit/editor-prosemirror/state';
2
- import { SelectionRange } from '../types';
3
- export declare const getSelectionRangeInRow: (rowIndex: number) => (tr: Transaction) => SelectionRange | undefined;
1
+ import type { Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ import type { SelectionRange } from '../types';
3
+ export declare const getSelectionRangeInRow: (startRowIndex: number, endRowIndex?: number) => (tr: Transaction) => SelectionRange | undefined;
@@ -1,5 +1,5 @@
1
1
  import type { Transaction } from '@atlaskit/editor-prosemirror/state';
2
- export declare const moveColumn: (originColumnIndex: number, targetColumnIndex: number, options?: {
2
+ export declare const moveColumn: (originColumnIndex: number | number[], targetColumnIndex: number, options?: {
3
3
  tryToFit: boolean;
4
4
  direction: number;
5
5
  }) => (tr: Transaction) => Transaction;
@@ -1,5 +1,5 @@
1
- import type { Transaction } from '@atlaskit/editor-prosemirror/state';
2
- export declare const moveRow: (originRowIndex: number, targetRowIndex: number, options?: {
1
+ import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const moveRow: (state: EditorState, originRowIndex: number | number[], targetRowIndex: number, options?: {
3
3
  tryToFit: boolean;
4
4
  direction: number;
5
5
  }) => (tr: Transaction) => Transaction;
@@ -2,5 +2,7 @@ import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
2
2
  import type { Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  export declare const selectColumn: (index: number, expand?: boolean) => (tr: Transaction) => Transaction;
4
4
  export declare const selectRow: (index: number, expand?: boolean) => (tr: Transaction) => Transaction;
5
+ export declare const selectRows: (indexes: number[]) => (tr: Transaction) => Transaction;
6
+ export declare const selectColumns: (indexes: number[]) => (tr: Transaction) => Transaction;
5
7
  export declare const selectTable: (tr: Transaction) => Transaction;
6
8
  export declare const selectTableClosestToPos: (tr: Transaction, $pos: ResolvedPos) => Transaction;
@@ -27,7 +27,7 @@ export { normalizeSelection } from './utils/normalize-selection';
27
27
  export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos, } from './utils/remove-column';
28
28
  export { removeRowAt, removeSelectedRows, removeRowClosestToPos, } from './utils/remove-row';
29
29
  export { removeTable } from './utils/remove-table';
30
- export { selectColumn, selectRow, selectTable } from './utils/select-nodes';
30
+ export { selectColumn, selectColumns, selectRow, selectRows, selectTable, } from './utils/select-nodes';
31
31
  export { selectionCell } from './utils/selection-cell';
32
32
  export { selectedRect } from './utils/selection-rect';
33
33
  export type { SelectionRect } from './utils/selection-rect';
@@ -1,3 +1,3 @@
1
- import { Transaction } from '@atlaskit/editor-prosemirror/state';
2
- import { SelectionRange } from '../types';
3
- export declare const getSelectionRangeInRow: (rowIndex: number) => (tr: Transaction) => SelectionRange | undefined;
1
+ import type { Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ import type { SelectionRange } from '../types';
3
+ export declare const getSelectionRangeInRow: (startRowIndex: number, endRowIndex?: number) => (tr: Transaction) => SelectionRange | undefined;
@@ -1,5 +1,5 @@
1
1
  import type { Transaction } from '@atlaskit/editor-prosemirror/state';
2
- export declare const moveColumn: (originColumnIndex: number, targetColumnIndex: number, options?: {
2
+ export declare const moveColumn: (originColumnIndex: number | number[], targetColumnIndex: number, options?: {
3
3
  tryToFit: boolean;
4
4
  direction: number;
5
5
  }) => (tr: Transaction) => Transaction;
@@ -1,5 +1,5 @@
1
- import type { Transaction } from '@atlaskit/editor-prosemirror/state';
2
- export declare const moveRow: (originRowIndex: number, targetRowIndex: number, options?: {
1
+ import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const moveRow: (state: EditorState, originRowIndex: number | number[], targetRowIndex: number, options?: {
3
3
  tryToFit: boolean;
4
4
  direction: number;
5
5
  }) => (tr: Transaction) => Transaction;
@@ -2,5 +2,7 @@ import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
2
2
  import type { Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  export declare const selectColumn: (index: number, expand?: boolean) => (tr: Transaction) => Transaction;
4
4
  export declare const selectRow: (index: number, expand?: boolean) => (tr: Transaction) => Transaction;
5
+ export declare const selectRows: (indexes: number[]) => (tr: Transaction) => Transaction;
6
+ export declare const selectColumns: (indexes: number[]) => (tr: Transaction) => Transaction;
5
7
  export declare const selectTable: (tr: Transaction) => Transaction;
6
8
  export declare const selectTableClosestToPos: (tr: Transaction, $pos: ResolvedPos) => Transaction;
@@ -27,7 +27,7 @@ export { normalizeSelection } from './utils/normalize-selection';
27
27
  export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos, } from './utils/remove-column';
28
28
  export { removeRowAt, removeSelectedRows, removeRowClosestToPos, } from './utils/remove-row';
29
29
  export { removeTable } from './utils/remove-table';
30
- export { selectColumn, selectRow, selectTable } from './utils/select-nodes';
30
+ export { selectColumn, selectColumns, selectRow, selectRows, selectTable, } from './utils/select-nodes';
31
31
  export { selectionCell } from './utils/selection-cell';
32
32
  export { selectedRect } from './utils/selection-rect';
33
33
  export type { SelectionRect } from './utils/selection-rect';
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-tables",
3
- "version": "2.3.17",
3
+ "version": "2.4.0",
4
4
  "description": "A package that contains common classes and utility functions for editor tables",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
7
7
  },
8
- "repository": "https://bitbucket.org/atlassian/atlassian-frontend",
8
+ "repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
9
9
  "author": "Atlassian Pty Ltd",
10
10
  "license": "Apache-2.0",
11
11
  "main": "dist/cjs/index.js",