handsontable 0.0.0-next-e5dbebc-20240319 → 0.0.0-next-a7270c3-20240320

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.

Potentially problematic release.


This version of handsontable might be problematic. Click here for more details.

Files changed (98) hide show
  1. package/3rdparty/walkontable/src/cell/range.d.ts +1 -2
  2. package/3rdparty/walkontable/src/cell/range.js +5 -22
  3. package/3rdparty/walkontable/src/cell/range.mjs +5 -22
  4. package/base.js +2 -2
  5. package/base.mjs +2 -2
  6. package/core/viewportScroll/index.js +1 -4
  7. package/core/viewportScroll/index.mjs +1 -4
  8. package/core.d.ts +3 -4
  9. package/core.js +21 -76
  10. package/core.mjs +21 -76
  11. package/dist/handsontable.css +2 -2
  12. package/dist/handsontable.full.css +2 -2
  13. package/dist/handsontable.full.js +1357 -2619
  14. package/dist/handsontable.full.min.css +2 -2
  15. package/dist/handsontable.full.min.js +71 -71
  16. package/dist/handsontable.js +1361 -2623
  17. package/dist/handsontable.min.css +2 -2
  18. package/dist/handsontable.min.js +19 -19
  19. package/editorManager.js +8 -12
  20. package/editorManager.mjs +8 -12
  21. package/focusManager.js +1 -7
  22. package/focusManager.mjs +1 -7
  23. package/helpers/mixed.js +1 -1
  24. package/helpers/mixed.mjs +1 -1
  25. package/package.json +1 -1
  26. package/pluginHooks.d.ts +0 -4
  27. package/pluginHooks.js +1 -69
  28. package/pluginHooks.mjs +1 -69
  29. package/plugins/collapsibleColumns/collapsibleColumns.js +3 -9
  30. package/plugins/collapsibleColumns/collapsibleColumns.mjs +3 -9
  31. package/plugins/columnSorting/columnSorting.js +2 -8
  32. package/plugins/columnSorting/columnSorting.mjs +2 -8
  33. package/plugins/contextMenu/menu/defaultShortcutsList.js +10 -26
  34. package/plugins/contextMenu/menu/defaultShortcutsList.mjs +10 -26
  35. package/plugins/mergeCells/calculations/selection.js +70 -1
  36. package/plugins/mergeCells/calculations/selection.mjs +70 -1
  37. package/plugins/mergeCells/cellsCollection.js +0 -116
  38. package/plugins/mergeCells/cellsCollection.mjs +0 -116
  39. package/plugins/mergeCells/contextMenuItem/toggleMerge.js +1 -11
  40. package/plugins/mergeCells/contextMenuItem/toggleMerge.mjs +1 -11
  41. package/plugins/mergeCells/mergeCells.js +196 -337
  42. package/plugins/mergeCells/mergeCells.mjs +196 -337
  43. package/plugins/multiColumnSorting/multiColumnSorting.js +2 -8
  44. package/plugins/multiColumnSorting/multiColumnSorting.mjs +2 -8
  45. package/plugins/nestedHeaders/nestedHeaders.js +0 -1
  46. package/plugins/nestedHeaders/nestedHeaders.mjs +0 -1
  47. package/plugins/nestedRows/nestedRows.js +3 -9
  48. package/plugins/nestedRows/nestedRows.mjs +3 -9
  49. package/renderers/checkboxRenderer/checkboxRenderer.js +5 -8
  50. package/renderers/checkboxRenderer/checkboxRenderer.mjs +5 -8
  51. package/selection/highlight/visualSelection.js +0 -2
  52. package/selection/highlight/visualSelection.mjs +0 -2
  53. package/selection/selection.js +40 -209
  54. package/selection/selection.mjs +39 -208
  55. package/selection/transformation.js +32 -83
  56. package/selection/transformation.mjs +32 -83
  57. package/shortcutContexts/commands/editor/closeAndSave.js +2 -2
  58. package/shortcutContexts/commands/editor/closeAndSave.mjs +2 -2
  59. package/shortcutContexts/commands/editor/open.js +3 -18
  60. package/shortcutContexts/commands/editor/open.mjs +3 -18
  61. package/shortcutContexts/commands/extendCellsSelection/down.js +1 -1
  62. package/shortcutContexts/commands/extendCellsSelection/down.mjs +1 -1
  63. package/shortcutContexts/commands/extendCellsSelection/left.js +1 -1
  64. package/shortcutContexts/commands/extendCellsSelection/left.mjs +1 -1
  65. package/shortcutContexts/commands/extendCellsSelection/right.js +1 -1
  66. package/shortcutContexts/commands/extendCellsSelection/right.mjs +1 -1
  67. package/shortcutContexts/commands/extendCellsSelection/toColumns.js +1 -1
  68. package/shortcutContexts/commands/extendCellsSelection/toColumns.mjs +1 -1
  69. package/shortcutContexts/commands/extendCellsSelection/toMostBottom.js +1 -3
  70. package/shortcutContexts/commands/extendCellsSelection/toMostBottom.mjs +1 -3
  71. package/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.js +3 -9
  72. package/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.mjs +3 -9
  73. package/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.js +3 -10
  74. package/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.mjs +3 -10
  75. package/shortcutContexts/commands/extendCellsSelection/toMostLeft.js +1 -3
  76. package/shortcutContexts/commands/extendCellsSelection/toMostLeft.mjs +1 -3
  77. package/shortcutContexts/commands/extendCellsSelection/toMostRight.js +1 -3
  78. package/shortcutContexts/commands/extendCellsSelection/toMostRight.mjs +1 -3
  79. package/shortcutContexts/commands/extendCellsSelection/toMostTop.js +1 -3
  80. package/shortcutContexts/commands/extendCellsSelection/toMostTop.mjs +1 -3
  81. package/shortcutContexts/commands/extendCellsSelection/toRows.js +1 -1
  82. package/shortcutContexts/commands/extendCellsSelection/toRows.mjs +1 -1
  83. package/shortcutContexts/commands/extendCellsSelection/up.js +1 -1
  84. package/shortcutContexts/commands/extendCellsSelection/up.mjs +1 -1
  85. package/shortcutContexts/commands/moveCellSelection/inlineEnd.js +1 -6
  86. package/shortcutContexts/commands/moveCellSelection/inlineEnd.mjs +1 -6
  87. package/shortcutContexts/commands/moveCellSelection/inlineStart.js +1 -6
  88. package/shortcutContexts/commands/moveCellSelection/inlineStart.mjs +1 -6
  89. package/shortcutContexts/grid.js +2 -2
  90. package/shortcutContexts/grid.mjs +2 -2
  91. package/shortcuts/context.js +1 -2
  92. package/shortcuts/context.mjs +1 -2
  93. package/utils/dataStructures/linkedList.js +1 -6
  94. package/utils/dataStructures/linkedList.mjs +1 -6
  95. package/core/viewportScroll/scrollStrategies/focusScroll.js +0 -15
  96. package/core/viewportScroll/scrollStrategies/focusScroll.mjs +0 -11
  97. package/plugins/mergeCells/focusOrder.js +0 -303
  98. package/plugins/mergeCells/focusOrder.mjs +0 -298
@@ -17,7 +17,6 @@ var _number = require("../../helpers/number");
17
17
  var _utils = require("./utils");
18
18
  var _element = require("../../helpers/dom/element");
19
19
  var _browser = require("../../helpers/browser");
20
- var _focusOrder2 = require("./focusOrder");
21
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
21
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
23
22
  function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
@@ -73,9 +72,7 @@ const SHORTCUTS_GROUP = PLUGIN_KEY;
73
72
  * ```
74
73
  * :::
75
74
  */
76
- var _lastSelectedFocus = /*#__PURE__*/new WeakMap();
77
- var _lastFocusDelta = /*#__PURE__*/new WeakMap();
78
- var _focusOrder = /*#__PURE__*/new WeakMap();
75
+ var _lastDesiredCoords = /*#__PURE__*/new WeakMap();
79
76
  var _MergeCells_brand = /*#__PURE__*/new WeakSet();
80
77
  class MergeCells extends _base.BasePlugin {
81
78
  constructor() {
@@ -106,32 +103,9 @@ class MergeCells extends _base.BasePlugin {
106
103
  */
107
104
  _defineProperty(this, "selectionCalculations", null);
108
105
  /**
109
- * The holder for the last selected focus coordinates. This allows keeping the correct coordinates in cases after the
110
- * focus is moved out of the merged cell.
111
- *
112
106
  * @type {CellCoords}
113
107
  */
114
- _classPrivateFieldInitSpec(this, _lastSelectedFocus, null);
115
- /**
116
- * The last used transformation delta.
117
- *
118
- * @type {{ row: number, col: number }}
119
- */
120
- _classPrivateFieldInitSpec(this, _lastFocusDelta, {
121
- row: 0,
122
- col: 0
123
- });
124
- /**
125
- * The module responsible for providing the correct focus order (vertical and horizontal) within a selection that
126
- * contains merged cells.
127
- *
128
- * @type {FocusOrder}
129
- */
130
- _classPrivateFieldInitSpec(this, _focusOrder, new _focusOrder2.FocusOrder({
131
- mergedCellsGetter: (row, column) => this.mergedCellsCollection.get(row, column),
132
- rowIndexMapper: this.hot.rowIndexMapper,
133
- columnIndexMapper: this.hot.columnIndexMapper
134
- }));
108
+ _classPrivateFieldInitSpec(this, _lastDesiredCoords, null);
135
109
  }
136
110
  static get PLUGIN_KEY() {
137
111
  return PLUGIN_KEY;
@@ -166,17 +140,17 @@ class MergeCells extends _base.BasePlugin {
166
140
  }
167
141
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterInit).call(_this, ...args);
168
142
  });
169
- this.addHook('modifyTransformFocus', function () {
143
+ this.addHook('modifyTransformStart', function () {
170
144
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
171
145
  args[_key2] = arguments[_key2];
172
146
  }
173
- return _assertClassBrand(_MergeCells_brand, _this, _onModifyTransformFocus).call(_this, ...args);
147
+ return _assertClassBrand(_MergeCells_brand, _this, _onModifyTransformStart).call(_this, ...args);
174
148
  });
175
- this.addHook('modifyTransformStart', function () {
149
+ this.addHook('afterModifyTransformStart', function () {
176
150
  for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
177
151
  args[_key3] = arguments[_key3];
178
152
  }
179
- return _assertClassBrand(_MergeCells_brand, _this, _onModifyTransformStart).call(_this, ...args);
153
+ return _assertClassBrand(_MergeCells_brand, _this, _onAfterModifyTransformStart).call(_this, ...args);
180
154
  });
181
155
  this.addHook('modifyTransformEnd', function () {
182
156
  for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
@@ -184,11 +158,11 @@ class MergeCells extends _base.BasePlugin {
184
158
  }
185
159
  return _assertClassBrand(_MergeCells_brand, _this, _onModifyTransformEnd).call(_this, ...args);
186
160
  });
187
- this.addHook('beforeSelectionHighlightSet', function () {
161
+ this.addHook('modifyGetCellCoords', function () {
188
162
  for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
189
163
  args[_key5] = arguments[_key5];
190
164
  }
191
- return _assertClassBrand(_MergeCells_brand, _this, _onBeforeSelectionHighlightSet).call(_this, ...args);
165
+ return _assertClassBrand(_MergeCells_brand, _this, _onModifyGetCellCoords).call(_this, ...args);
192
166
  });
193
167
  this.addHook('beforeSetRangeStart', function () {
194
168
  for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
@@ -202,123 +176,105 @@ class MergeCells extends _base.BasePlugin {
202
176
  }
203
177
  return _assertClassBrand(_MergeCells_brand, _this, _onBeforeSetRangeStart).call(_this, ...args);
204
178
  });
205
- this.addHook('beforeSelectionFocusSet', function () {
179
+ this.addHook('beforeSetRangeEnd', function () {
206
180
  for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
207
181
  args[_key8] = arguments[_key8];
208
182
  }
209
- return _assertClassBrand(_MergeCells_brand, _this, _onBeforeSelectionFocusSet).call(_this, ...args);
183
+ return _assertClassBrand(_MergeCells_brand, _this, _onBeforeSetRangeEnd).call(_this, ...args);
210
184
  });
211
- this.addHook('afterSelectionFocusSet', function () {
185
+ this.addHook('afterIsMultipleSelection', function () {
212
186
  for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
213
187
  args[_key9] = arguments[_key9];
214
188
  }
215
- return _assertClassBrand(_MergeCells_brand, _this, _onAfterSelectionFocusSet).call(_this, ...args);
216
- });
217
- this.addHook('afterSelectionEnd', function () {
218
- for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
219
- args[_key10] = arguments[_key10];
220
- }
221
- return _assertClassBrand(_MergeCells_brand, _this, _onAfterSelectionEnd).call(_this, ...args);
222
- });
223
- this.addHook('modifyGetCellCoords', function () {
224
- for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) {
225
- args[_key11] = arguments[_key11];
226
- }
227
- return _assertClassBrand(_MergeCells_brand, _this, _onModifyGetCellCoords).call(_this, ...args);
228
- });
229
- this.addHook('afterIsMultipleSelection', function () {
230
- for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) {
231
- args[_key12] = arguments[_key12];
232
- }
233
189
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterIsMultipleSelection).call(_this, ...args);
234
190
  });
235
191
  this.addHook('afterRenderer', function () {
236
- for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) {
237
- args[_key13] = arguments[_key13];
192
+ for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
193
+ args[_key10] = arguments[_key10];
238
194
  }
239
195
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterRenderer).call(_this, ...args);
240
196
  });
241
197
  this.addHook('afterContextMenuDefaultOptions', function () {
242
- for (var _len14 = arguments.length, args = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) {
243
- args[_key14] = arguments[_key14];
198
+ for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) {
199
+ args[_key11] = arguments[_key11];
244
200
  }
245
201
  return _assertClassBrand(_MergeCells_brand, _this, _addMergeActionsToContextMenu).call(_this, ...args);
246
202
  });
247
203
  this.addHook('afterGetCellMeta', function () {
248
- for (var _len15 = arguments.length, args = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) {
249
- args[_key15] = arguments[_key15];
204
+ for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) {
205
+ args[_key12] = arguments[_key12];
250
206
  }
251
207
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterGetCellMeta).call(_this, ...args);
252
208
  });
253
209
  this.addHook('afterViewportRowCalculatorOverride', function () {
254
- for (var _len16 = arguments.length, args = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) {
255
- args[_key16] = arguments[_key16];
210
+ for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) {
211
+ args[_key13] = arguments[_key13];
256
212
  }
257
213
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterViewportRowCalculatorOverride).call(_this, ...args);
258
214
  });
259
215
  this.addHook('afterViewportColumnCalculatorOverride', function () {
260
- for (var _len17 = arguments.length, args = new Array(_len17), _key17 = 0; _key17 < _len17; _key17++) {
261
- args[_key17] = arguments[_key17];
216
+ for (var _len14 = arguments.length, args = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) {
217
+ args[_key14] = arguments[_key14];
262
218
  }
263
219
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterViewportColumnCalculatorOverride).call(_this, ...args);
264
220
  });
265
221
  this.addHook('modifyAutofillRange', function () {
266
- for (var _len18 = arguments.length, args = new Array(_len18), _key18 = 0; _key18 < _len18; _key18++) {
267
- args[_key18] = arguments[_key18];
222
+ for (var _len15 = arguments.length, args = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) {
223
+ args[_key15] = arguments[_key15];
268
224
  }
269
225
  return _assertClassBrand(_MergeCells_brand, _this, _onModifyAutofillRange).call(_this, ...args);
270
226
  });
271
227
  this.addHook('afterCreateCol', function () {
272
- for (var _len19 = arguments.length, args = new Array(_len19), _key19 = 0; _key19 < _len19; _key19++) {
273
- args[_key19] = arguments[_key19];
228
+ for (var _len16 = arguments.length, args = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) {
229
+ args[_key16] = arguments[_key16];
274
230
  }
275
231
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterCreateCol).call(_this, ...args);
276
232
  });
277
233
  this.addHook('afterRemoveCol', function () {
278
- for (var _len20 = arguments.length, args = new Array(_len20), _key20 = 0; _key20 < _len20; _key20++) {
279
- args[_key20] = arguments[_key20];
234
+ for (var _len17 = arguments.length, args = new Array(_len17), _key17 = 0; _key17 < _len17; _key17++) {
235
+ args[_key17] = arguments[_key17];
280
236
  }
281
237
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterRemoveCol).call(_this, ...args);
282
238
  });
283
239
  this.addHook('afterCreateRow', function () {
284
- for (var _len21 = arguments.length, args = new Array(_len21), _key21 = 0; _key21 < _len21; _key21++) {
285
- args[_key21] = arguments[_key21];
240
+ for (var _len18 = arguments.length, args = new Array(_len18), _key18 = 0; _key18 < _len18; _key18++) {
241
+ args[_key18] = arguments[_key18];
286
242
  }
287
243
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterCreateRow).call(_this, ...args);
288
244
  });
289
245
  this.addHook('afterRemoveRow', function () {
290
- for (var _len22 = arguments.length, args = new Array(_len22), _key22 = 0; _key22 < _len22; _key22++) {
291
- args[_key22] = arguments[_key22];
246
+ for (var _len19 = arguments.length, args = new Array(_len19), _key19 = 0; _key19 < _len19; _key19++) {
247
+ args[_key19] = arguments[_key19];
292
248
  }
293
249
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterRemoveRow).call(_this, ...args);
294
250
  });
295
251
  this.addHook('afterChange', function () {
296
- for (var _len23 = arguments.length, args = new Array(_len23), _key23 = 0; _key23 < _len23; _key23++) {
297
- args[_key23] = arguments[_key23];
252
+ for (var _len20 = arguments.length, args = new Array(_len20), _key20 = 0; _key20 < _len20; _key20++) {
253
+ args[_key20] = arguments[_key20];
298
254
  }
299
255
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterChange).call(_this, ...args);
300
256
  });
301
257
  this.addHook('beforeDrawBorders', function () {
302
- for (var _len24 = arguments.length, args = new Array(_len24), _key24 = 0; _key24 < _len24; _key24++) {
303
- args[_key24] = arguments[_key24];
258
+ for (var _len21 = arguments.length, args = new Array(_len21), _key21 = 0; _key21 < _len21; _key21++) {
259
+ args[_key21] = arguments[_key21];
304
260
  }
305
261
  return _assertClassBrand(_MergeCells_brand, _this, _onBeforeDrawAreaBorders).call(_this, ...args);
306
262
  });
307
263
  this.addHook('afterDrawSelection', function () {
308
- for (var _len25 = arguments.length, args = new Array(_len25), _key25 = 0; _key25 < _len25; _key25++) {
309
- args[_key25] = arguments[_key25];
264
+ for (var _len22 = arguments.length, args = new Array(_len22), _key22 = 0; _key22 < _len22; _key22++) {
265
+ args[_key22] = arguments[_key22];
310
266
  }
311
267
  return _assertClassBrand(_MergeCells_brand, _this, _onAfterDrawSelection).call(_this, ...args);
312
268
  });
313
269
  this.addHook('beforeRemoveCellClassNames', function () {
314
- for (var _len26 = arguments.length, args = new Array(_len26), _key26 = 0; _key26 < _len26; _key26++) {
315
- args[_key26] = arguments[_key26];
270
+ for (var _len23 = arguments.length, args = new Array(_len23), _key23 = 0; _key23 < _len23; _key23++) {
271
+ args[_key23] = arguments[_key23];
316
272
  }
317
273
  return _assertClassBrand(_MergeCells_brand, _this, _onBeforeRemoveCellClassNames).call(_this, ...args);
318
274
  });
319
275
  this.addHook('beforeBeginEditing', function () {
320
- for (var _len27 = arguments.length, args = new Array(_len27), _key27 = 0; _key27 < _len27; _key27++) {
321
- args[_key27] = arguments[_key27];
276
+ for (var _len24 = arguments.length, args = new Array(_len24), _key24 = 0; _key24 < _len24; _key24++) {
277
+ args[_key24] = arguments[_key24];
322
278
  }
323
279
  return _assertClassBrand(_MergeCells_brand, _this, _onBeforeBeginEditing).call(_this, ...args);
324
280
  });
@@ -464,7 +420,9 @@ class MergeCells extends _base.BasePlugin {
464
420
  if (populatedNulls.length === 0) {
465
421
  return;
466
422
  }
467
- this.hot.setDataAtCell(populatedNulls);
423
+
424
+ // TODO: Change the `source` argument to a more meaningful value, e.g. `${this.pluginName}.clearCells`.
425
+ this.hot.setDataAtCell(populatedNulls, undefined, undefined, this.pluginName);
468
426
  }
469
427
  }
470
428
 
@@ -488,6 +446,25 @@ class MergeCells extends _base.BasePlugin {
488
446
  return auto ? true : this.validateSetting(newMergedCellInfo);
489
447
  }
490
448
 
449
+ /**
450
+ * Merge or unmerge, based on last selected range.
451
+ *
452
+ * @private
453
+ */
454
+ toggleMergeOnSelection() {
455
+ const currentRange = this.hot.getSelectedRangeLast();
456
+ if (!currentRange) {
457
+ return;
458
+ }
459
+ currentRange.setDirection(this.hot.isRtl() ? 'NE-SW' : 'NW-SE');
460
+ const {
461
+ from,
462
+ to
463
+ } = currentRange;
464
+ this.toggleMerge(currentRange);
465
+ this.hot.selectCell(from.row, from.col, to.row, to.col, false);
466
+ }
467
+
491
468
  /**
492
469
  * Merges the selection provided as a cell range.
493
470
  *
@@ -576,6 +553,7 @@ class MergeCells extends _base.BasePlugin {
576
553
  if (preventPopulation) {
577
554
  populationInfo = [mergeParent.row, mergeParent.col, clearedData];
578
555
  } else {
556
+ // TODO: Change the `source` argument to a more meaningful value, e.g. `${this.pluginName}.clearCells`.
579
557
  this.hot.populateFromArray(mergeParent.row, mergeParent.col, clearedData, undefined, undefined, this.pluginName);
580
558
  }
581
559
  if (!auto) {
@@ -882,191 +860,94 @@ function _onAfterIsMultipleSelection(isMultiple) {
882
860
  if (isMultiple) {
883
861
  const mergedCells = this.mergedCellsCollection.mergedCells;
884
862
  const selectionRange = this.hot.getSelectedRangeLast();
885
- const topStartCoords = selectionRange.getTopStartCorner();
886
- const bottomEndCoords = selectionRange.getBottomEndCorner();
887
863
  for (let group = 0; group < mergedCells.length; group += 1) {
888
- if (topStartCoords.row === mergedCells[group].row && topStartCoords.col === mergedCells[group].col && bottomEndCoords.row === mergedCells[group].row + mergedCells[group].rowspan - 1 && bottomEndCoords.col === mergedCells[group].col + mergedCells[group].colspan - 1) {
864
+ if (selectionRange.from.row === mergedCells[group].row && selectionRange.from.col === mergedCells[group].col && selectionRange.to.row === mergedCells[group].row + mergedCells[group].rowspan - 1 && selectionRange.to.col === mergedCells[group].col + mergedCells[group].colspan - 1) {
889
865
  return false;
890
866
  }
891
867
  }
892
868
  }
893
869
  return isMultiple;
894
870
  }
895
- /**
896
- * `modifyTransformFocus` hook callback.
897
- *
898
- * @param {object} delta The transformation delta.
899
- */
900
- function _onModifyTransformFocus(delta) {
901
- _classPrivateFieldGet(_lastFocusDelta, this).row = delta.row;
902
- _classPrivateFieldGet(_lastFocusDelta, this).col = delta.col;
903
- }
904
871
  /**
905
872
  * `modifyTransformStart` hook callback.
906
873
  *
907
874
  * @param {object} delta The transformation delta.
908
875
  */
909
876
  function _onModifyTransformStart(delta) {
910
- const selectedRange = this.hot.getSelectedRangeLast();
911
- const {
912
- highlight
913
- } = selectedRange;
914
- const {
915
- columnIndexMapper,
916
- rowIndexMapper
917
- } = this.hot;
918
- if (_classPrivateFieldGet(_lastSelectedFocus, this)) {
919
- if (rowIndexMapper.getRenderableFromVisualIndex(_classPrivateFieldGet(_lastSelectedFocus, this).row) !== null) {
920
- highlight.row = _classPrivateFieldGet(_lastSelectedFocus, this).row;
877
+ const currentlySelectedRange = this.hot.getSelectedRangeLast();
878
+ let newDelta = {
879
+ row: delta.row,
880
+ col: delta.col
881
+ };
882
+ let nextPosition = null;
883
+ const currentPosition = this.hot._createCellCoords(currentlySelectedRange.highlight.row, currentlySelectedRange.highlight.col);
884
+ const mergedParent = this.mergedCellsCollection.get(currentPosition.row, currentPosition.col);
885
+ if (!_classPrivateFieldGet(_lastDesiredCoords, this)) {
886
+ _classPrivateFieldSet(_lastDesiredCoords, this, this.hot._createCellCoords(null, null));
887
+ }
888
+ if (mergedParent) {
889
+ // only merge selected
890
+ const mergeTopLeft = this.hot._createCellCoords(mergedParent.row, mergedParent.col);
891
+ const mergeBottomRight = this.hot._createCellCoords(mergedParent.row + mergedParent.rowspan - 1, mergedParent.col + mergedParent.colspan - 1);
892
+ const mergeRange = this.hot._createCellRange(mergeTopLeft, mergeTopLeft, mergeBottomRight);
893
+ if (!mergeRange.includes(_classPrivateFieldGet(_lastDesiredCoords, this))) {
894
+ _classPrivateFieldSet(_lastDesiredCoords, this, this.hot._createCellCoords(null, null)); // reset outdated version of lastDesiredCoords
921
895
  }
922
- if (columnIndexMapper.getRenderableFromVisualIndex(_classPrivateFieldGet(_lastSelectedFocus, this).col) !== null) {
923
- highlight.col = _classPrivateFieldGet(_lastSelectedFocus, this).col;
896
+ newDelta.row = _classPrivateFieldGet(_lastDesiredCoords, this).row ? _classPrivateFieldGet(_lastDesiredCoords, this).row - currentPosition.row : newDelta.row;
897
+ newDelta.col = _classPrivateFieldGet(_lastDesiredCoords, this).col ? _classPrivateFieldGet(_lastDesiredCoords, this).col - currentPosition.col : newDelta.col;
898
+ if (delta.row > 0) {
899
+ // moving down
900
+ newDelta.row = mergedParent.row + mergedParent.rowspan - 1 - currentPosition.row + delta.row;
901
+ } else if (delta.row < 0) {
902
+ // moving up
903
+ newDelta.row = currentPosition.row - mergedParent.row + delta.row;
904
+ }
905
+ if (delta.col > 0) {
906
+ // moving right
907
+ newDelta.col = mergedParent.col + mergedParent.colspan - 1 - currentPosition.col + delta.col;
908
+ } else if (delta.col < 0) {
909
+ // moving left
910
+ newDelta.col = currentPosition.col - mergedParent.col + delta.col;
924
911
  }
925
- _classPrivateFieldSet(_lastSelectedFocus, this, null);
926
912
  }
927
- const mergedParent = this.mergedCellsCollection.get(highlight.row, highlight.col);
928
- if (!mergedParent) {
929
- return;
913
+ nextPosition = this.hot._createCellCoords(currentlySelectedRange.highlight.row + newDelta.row, currentlySelectedRange.highlight.col + newDelta.col);
914
+ const nextPositionMergedCell = this.mergedCellsCollection.get(nextPosition.row, nextPosition.col);
915
+ if (nextPositionMergedCell) {
916
+ // skipping the invisible cells in the merge range
917
+ const firstRenderableCoords = this.mergedCellsCollection.getFirstRenderableCoords(nextPositionMergedCell.row, nextPositionMergedCell.col);
918
+ _classPrivateFieldSet(_lastDesiredCoords, this, nextPosition);
919
+ newDelta = {
920
+ row: firstRenderableCoords.row - currentPosition.row,
921
+ col: firstRenderableCoords.col - currentPosition.col
922
+ };
930
923
  }
931
- const visualColumnIndexStart = mergedParent.col;
932
- const visualColumnIndexEnd = mergedParent.col + mergedParent.colspan - 1;
933
- if (delta.col < 0) {
934
- const nextColumn = highlight.col >= visualColumnIndexStart && highlight.col <= visualColumnIndexEnd ? visualColumnIndexStart - 1 : visualColumnIndexEnd;
935
- const notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(nextColumn, -1);
936
- if (notHiddenColumnIndex === null) {
937
- // There are no visible columns anymore, so move the selection out of the table edge. This will
938
- // be processed by the selection Transformer class as a move selection to the previous row (if autoWrapRow is enabled).
939
- delta.col = -this.hot.view.countRenderableColumnsInRange(0, highlight.col);
940
- } else {
941
- delta.col = -Math.max(this.hot.view.countRenderableColumnsInRange(notHiddenColumnIndex, highlight.col) - 1, 1);
942
- }
943
- } else if (delta.col > 0) {
944
- const nextColumn = highlight.col >= visualColumnIndexStart && highlight.col <= visualColumnIndexEnd ? visualColumnIndexEnd + 1 : visualColumnIndexStart;
945
- const notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(nextColumn, 1);
946
- if (notHiddenColumnIndex === null) {
947
- // There are no visible columns anymore, so move the selection out of the table edge. This will
948
- // be processed by the selection Transformer class as a move selection to the next row (if autoWrapRow is enabled).
949
- delta.col = this.hot.view.countRenderableColumnsInRange(highlight.col, this.hot.countCols());
950
- } else {
951
- delta.col = Math.max(this.hot.view.countRenderableColumnsInRange(highlight.col, notHiddenColumnIndex) - 1, 1);
952
- }
924
+ if (newDelta.row !== 0) {
925
+ delta.row = newDelta.row;
953
926
  }
954
- const visualRowIndexStart = mergedParent.row;
955
- const visualRowIndexEnd = mergedParent.row + mergedParent.rowspan - 1;
956
- if (delta.row < 0) {
957
- const nextRow = highlight.row >= visualRowIndexStart && highlight.row <= visualRowIndexEnd ? visualRowIndexStart - 1 : visualRowIndexEnd;
958
- const notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(nextRow, -1);
959
- if (notHiddenRowIndex === null) {
960
- // There are no visible rows anymore, so move the selection out of the table edge. This will
961
- // be processed by the selection Transformer class as a move selection to the previous column (if autoWrapCol is enabled).
962
- delta.row = -this.hot.view.countRenderableRowsInRange(0, highlight.row);
963
- } else {
964
- delta.row = -Math.max(this.hot.view.countRenderableRowsInRange(notHiddenRowIndex, highlight.row) - 1, 1);
965
- }
966
- } else if (delta.row > 0) {
967
- const nextRow = highlight.row >= visualRowIndexStart && highlight.row <= visualRowIndexEnd ? visualRowIndexEnd + 1 : visualRowIndexStart;
968
- const notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(nextRow, 1);
969
- if (notHiddenRowIndex === null) {
970
- // There are no visible rows anymore, so move the selection out of the table edge. This will
971
- // be processed by the selection Transformer class as a move selection to the next column (if autoWrapCol is enabled).
972
- delta.row = this.hot.view.countRenderableRowsInRange(highlight.row, this.hot.countRows());
973
- } else {
974
- delta.row = Math.max(this.hot.view.countRenderableRowsInRange(highlight.row, notHiddenRowIndex) - 1, 1);
975
- }
927
+ if (newDelta.col !== 0) {
928
+ delta.col = newDelta.col;
976
929
  }
977
930
  }
978
931
  /**
979
- * The hook allows to modify the delta transformation object necessary for correct selection end transformations.
980
- * The logic here handles "jumping over" merged merged cells, while selecting.
932
+ * `modifyTransformEnd` hook callback. Needed to handle "jumping over" merged merged cells, while selecting.
981
933
  *
982
- * @param {{ row: number, col: number }} delta The transformation delta.
934
+ * @param {object} delta The transformation delta.
983
935
  */
984
936
  function _onModifyTransformEnd(delta) {
985
- const selectedRange = this.hot.getSelectedRangeLast();
986
- const cloneRange = selectedRange.clone();
987
- const {
988
- to
989
- } = selectedRange;
990
- const {
991
- columnIndexMapper,
992
- rowIndexMapper
993
- } = this.hot;
994
- const expandCloneRange = (row, col) => {
995
- cloneRange.expand(this.hot._createCellCoords(row, col));
996
- for (let i = 0; i < this.mergedCellsCollection.mergedCells.length; i += 1) {
997
- cloneRange.expandByRange(this.mergedCellsCollection.mergedCells[i].getRange());
998
- }
999
- };
1000
- if (delta.col < 0) {
1001
- let nextColumn = this.mergedCellsCollection.getStartMostColumnIndex(selectedRange, to.col) + delta.col;
1002
- expandCloneRange(to.row, nextColumn);
1003
- if (selectedRange.getHorizontalDirection() === 'E-W' && cloneRange.getHorizontalDirection() === 'E-W') {
1004
- nextColumn = cloneRange.getTopStartCorner().col;
1005
- }
1006
- const notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(nextColumn, 1);
1007
- if (notHiddenColumnIndex !== null) {
1008
- delta.col = -Math.max(this.hot.view.countRenderableColumnsInRange(notHiddenColumnIndex, to.col) - 1, 1);
1009
- }
1010
- } else if (delta.col > 0) {
1011
- let nextColumn = this.mergedCellsCollection.getEndMostColumnIndex(selectedRange, to.col) + delta.col;
1012
- expandCloneRange(to.row, nextColumn);
1013
- if (selectedRange.getHorizontalDirection() === 'W-E' && cloneRange.getHorizontalDirection() === 'W-E') {
1014
- nextColumn = cloneRange.getBottomEndCorner().col;
1015
- }
1016
- const notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(nextColumn, -1);
1017
- if (notHiddenColumnIndex !== null) {
1018
- delta.col = Math.max(this.hot.view.countRenderableColumnsInRange(to.col, notHiddenColumnIndex) - 1, 1);
1019
- }
1020
- }
1021
- if (delta.row < 0) {
1022
- let nextRow = this.mergedCellsCollection.getTopMostRowIndex(selectedRange, to.row) + delta.row;
1023
- expandCloneRange(nextRow, to.col);
1024
- if (selectedRange.getVerticalDirection() === 'S-N' && cloneRange.getVerticalDirection() === 'S-N') {
1025
- nextRow = cloneRange.getTopStartCorner().row;
1026
- }
1027
- const notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(nextRow, 1);
1028
- if (notHiddenRowIndex !== null) {
1029
- delta.row = -Math.max(this.hot.view.countRenderableRowsInRange(notHiddenRowIndex, to.row) - 1, 1);
1030
- }
1031
- } else if (delta.row > 0) {
1032
- let nextRow = this.mergedCellsCollection.getBottomMostRowIndex(selectedRange, to.row) + delta.row;
1033
- expandCloneRange(nextRow, to.col);
1034
- if (selectedRange.getVerticalDirection() === 'N-S' && cloneRange.getVerticalDirection() === 'N-S') {
1035
- nextRow = cloneRange.getBottomStartCorner().row;
1036
- }
1037
- const notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(nextRow, -1);
1038
- if (notHiddenRowIndex !== null) {
1039
- delta.row = Math.max(this.hot.view.countRenderableRowsInRange(to.row, notHiddenRowIndex) - 1, 1);
1040
- }
1041
- }
1042
- }
1043
- /**
1044
- * The hook corrects the range (before drawing it) after the selection was made on the merged cells.
1045
- * It expands the range to cover the entire area of the selected merged cells.
1046
- */
1047
- function _onBeforeSelectionHighlightSet() {
1048
- const selectedRange = this.hot.getSelectedRangeLast();
1049
- const {
1050
- highlight
1051
- } = selectedRange;
1052
- if (this.hot.selection.isSelectedByColumnHeader() || this.hot.selection.isSelectedByRowHeader()) {
1053
- _classPrivateFieldSet(_lastSelectedFocus, this, highlight.clone());
1054
- return;
1055
- }
1056
- for (let i = 0; i < this.mergedCellsCollection.mergedCells.length; i += 1) {
1057
- selectedRange.expandByRange(this.mergedCellsCollection.mergedCells[i].getRange(), false);
1058
- }
1059
- // TODO: This is a workaround for an issue with the selection not being extended properly.
1060
- // In some cases when the merge cells are defined in random order the selection is not
1061
- // extended in that way that it covers all overlapped merge cells.
1062
- for (let i = 0; i < this.mergedCellsCollection.mergedCells.length; i += 1) {
1063
- selectedRange.expandByRange(this.mergedCellsCollection.mergedCells[i].getRange(), false);
1064
- }
1065
- const mergedParent = this.mergedCellsCollection.get(highlight.row, highlight.col);
1066
- _classPrivateFieldSet(_lastSelectedFocus, this, highlight.clone());
1067
- if (mergedParent) {
1068
- highlight.assign(mergedParent);
1069
- }
937
+ const currentSelectionRange = this.hot.getSelectedRangeLast();
938
+ const newDelta = (0, _object.clone)(delta);
939
+ const newSelectionRange = this.selectionCalculations.getUpdatedSelectionRange(currentSelectionRange, delta);
940
+ let tempDelta = (0, _object.clone)(newDelta);
941
+ const mergedCellsWithinRange = this.mergedCellsCollection.getWithinRange(newSelectionRange, true);
942
+ do {
943
+ tempDelta = (0, _object.clone)(newDelta);
944
+ this.selectionCalculations.getUpdatedSelectionRange(currentSelectionRange, newDelta);
945
+ (0, _array.arrayEach)(mergedCellsWithinRange, mergedCell => {
946
+ this.selectionCalculations.snapDelta(newDelta, currentSelectionRange, mergedCell);
947
+ });
948
+ } while (newDelta.row !== tempDelta.row || newDelta.col !== tempDelta.col);
949
+ delta.row = newDelta.row;
950
+ delta.col = newDelta.col;
1070
951
  }
1071
952
  /**
1072
953
  * `modifyGetCellCoords` hook callback. Swaps the `getCell` coords with the merged parent coords.
@@ -1145,104 +1026,51 @@ function _onAfterRenderer(TD, row, col) {
1145
1026
  (0, _utils.applySpanProperties)(TD, mergedCellCopy, row, col);
1146
1027
  }
1147
1028
  /**
1148
- * Clears the last selected coordinates before setting a new selection range.
1149
- */
1150
- function _onBeforeSetRangeStart() {
1151
- _classPrivateFieldSet(_lastSelectedFocus, this, null);
1152
- }
1153
- /**
1154
- * Detects if the last selected cell was a header cell if so update the order list active node for further
1155
- * computations.
1156
- */
1157
- function _onBeforeSelectionFocusSet() {
1158
- if (_classPrivateFieldGet(_lastSelectedFocus, this).isCell()) {
1159
- return;
1160
- }
1161
- const selectedRange = this.hot.getSelectedRangeLast();
1162
- const verticalDir = selectedRange.getVerticalDirection();
1163
- const horizontalDir = selectedRange.getHorizontalDirection();
1164
- const focusCoords = _classPrivateFieldGet(_lastSelectedFocus, this).clone().normalize();
1165
- _classPrivateFieldGet(_focusOrder, this).setActiveNode(focusCoords.row, focusCoords.col);
1166
- if (_classPrivateFieldGet(_lastFocusDelta, this).row > 0 || _classPrivateFieldGet(_lastFocusDelta, this).col > 0) {
1167
- _classPrivateFieldGet(_focusOrder, this).setPrevNodeAsActive();
1168
- } else if (horizontalDir === 'E-W' && _classPrivateFieldGet(_lastFocusDelta, this).col < 0 || verticalDir === 'S-N' && _classPrivateFieldGet(_lastFocusDelta, this).row < 0) {
1169
- _classPrivateFieldGet(_focusOrder, this).setNextNodeAsActive();
1170
- }
1171
- }
1172
- /**
1173
- * Changes the focus selection to the next or previous cell or merged cell position.
1029
+ * `beforeSetRangeStart` and `beforeSetRangeStartOnly` hook callback.
1030
+ * A selection within merge area should be rewritten to the start of merge area.
1174
1031
  *
1175
- * @param {number} row The visual row index.
1176
- * @param {number} column The visual column index.
1032
+ * @param {object} coords Cell coords.
1177
1033
  */
1178
- function _onAfterSelectionFocusSet(row, column) {
1179
- const selectedRange = this.hot.getSelectedRangeLast();
1180
- const {
1181
- columnIndexMapper,
1182
- rowIndexMapper
1183
- } = this.hot;
1184
- let notHiddenRowIndex = null;
1185
- let notHiddenColumnIndex = null;
1186
- if (_classPrivateFieldGet(_lastFocusDelta, this).col < 0) {
1187
- const {
1188
- rowEnd,
1189
- colEnd
1190
- } = _classPrivateFieldGet(_focusOrder, this).getPrevHorizontalNode();
1191
- notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(colEnd, -1);
1192
- notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(rowEnd, -1);
1193
- } else if (_classPrivateFieldGet(_lastFocusDelta, this).col > 0) {
1194
- const {
1195
- rowStart,
1196
- colStart
1197
- } = _classPrivateFieldGet(_focusOrder, this).getNextHorizontalNode();
1198
- notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(colStart, 1);
1199
- notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(rowStart, 1);
1200
- } else if (_classPrivateFieldGet(_lastFocusDelta, this).row < 0) {
1201
- const {
1202
- rowEnd,
1203
- colEnd
1204
- } = _classPrivateFieldGet(_focusOrder, this).getPrevVerticalNode();
1205
- notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(colEnd, -1);
1206
- notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(rowEnd, -1);
1207
- } else if (_classPrivateFieldGet(_lastFocusDelta, this).row > 0) {
1208
- const {
1209
- rowStart,
1210
- colStart
1211
- } = _classPrivateFieldGet(_focusOrder, this).getNextVerticalNode();
1212
- notHiddenColumnIndex = columnIndexMapper.getNearestNotHiddenIndex(colStart, 1);
1213
- notHiddenRowIndex = rowIndexMapper.getNearestNotHiddenIndex(rowStart, 1);
1214
- }
1215
- if (notHiddenRowIndex !== null || notHiddenColumnIndex !== null) {
1216
- const coords = this.hot._createCellCoords(notHiddenRowIndex, notHiddenColumnIndex);
1034
+ function _onBeforeSetRangeStart(coords) {
1035
+ // TODO: It is a workaround, but probably this hook may be needed. Every selection on the merge area
1036
+ // could set start point of the selection to the start of the merge area. However, logic inside `expandByRange` need
1037
+ // an initial start point. Click on the merge cell when there are some hidden indexes break the logic in some cases.
1038
+ // Please take a look at #7010 for more information. I'm not sure if selection directions are calculated properly
1039
+ // and what was idea for flipping direction inside `expandByRange` method.
1040
+ if (this.mergedCellsCollection.isFirstRenderableMergedCell(coords.row, coords.col)) {
1217
1041
  const mergeParent = this.mergedCellsCollection.get(coords.row, coords.col);
1218
- const focusHighlight = this.hot.selection.highlight.getFocus();
1219
- row = coords.row;
1220
- column = coords.col;
1221
- if (mergeParent) {
1222
- selectedRange.highlight.assign({
1223
- row: this.hot.rowIndexMapper.getNearestNotHiddenIndex(mergeParent.row, 1),
1224
- col: this.hot.columnIndexMapper.getNearestNotHiddenIndex(mergeParent.col, 1)
1225
- });
1226
- } else {
1227
- selectedRange.highlight.assign(coords);
1228
- }
1229
- focusHighlight.clear();
1230
- focusHighlight.add(coords).commit();
1042
+ [coords.row, coords.col] = [mergeParent.row, mergeParent.col];
1231
1043
  }
1232
- _classPrivateFieldGet(_focusOrder, this).setActiveNode(row, column);
1233
- _classPrivateFieldSet(_lastFocusDelta, this, {
1234
- row: 0,
1235
- col: 0
1236
- });
1237
1044
  }
1238
1045
  /**
1239
- * Creates the horizontal and vertical cells order matrix (linked lists) for focused cell.
1046
+ * `beforeSetRangeEnd` hook callback.
1047
+ * While selecting cells with keyboard or mouse, make sure that rectangular area is expanded to the extent of the
1048
+ * merged cell.
1049
+ *
1050
+ * Note: Please keep in mind that callback may modify both start and end range coordinates by the reference.
1051
+ *
1052
+ * @param {object} coords Cell coords.
1240
1053
  */
1241
- function _onAfterSelectionEnd() {
1242
- const selection = this.hot.getSelectedRangeLast();
1243
- if (!selection.isHeader()) {
1244
- _classPrivateFieldGet(_focusOrder, this).buildFocusOrder(this.hot.getSelectedRangeLast());
1054
+ function _onBeforeSetRangeEnd(coords) {
1055
+ const selRange = this.hot.getSelectedRangeLast();
1056
+ selRange.highlight = this.hot._createCellCoords(selRange.highlight.row, selRange.highlight.col); // clone in case we will modify its reference
1057
+ selRange.to = coords;
1058
+ let rangeExpanded = false;
1059
+ if (this.hot.selection.isSelectedByColumnHeader() || this.hot.selection.isSelectedByRowHeader()) {
1060
+ return;
1245
1061
  }
1062
+ do {
1063
+ rangeExpanded = false;
1064
+ for (let i = 0; i < this.mergedCellsCollection.mergedCells.length; i += 1) {
1065
+ const cellInfo = this.mergedCellsCollection.mergedCells[i];
1066
+ const mergedCellRange = cellInfo.getRange();
1067
+ if (selRange.expandByRange(mergedCellRange)) {
1068
+ coords.row = selRange.to.row;
1069
+ coords.col = selRange.to.col;
1070
+ rangeExpanded = true;
1071
+ }
1072
+ }
1073
+ } while (rangeExpanded);
1246
1074
  }
1247
1075
  /**
1248
1076
  * The `afterGetCellMeta` hook callback.
@@ -1371,6 +1199,37 @@ function _onBeforeDrawAreaBorders(corners, className) {
1371
1199
  });
1372
1200
  }
1373
1201
  }
1202
+ /**
1203
+ * `afterModifyTransformStart` hook callback. Fixes a problem with navigating through merged cells at the edges of
1204
+ * the table with the <kbd>**Enter**</kbd>/<kbd>**Shift**</kbd>+<kbd>**Enter**</kbd>/<kbd>**Tab**</kbd>/<kbd>**Shift**</kbd>+<kbd>**Tab**</kbd> keys.
1205
+ *
1206
+ * @param {CellCoords} coords Coordinates of the to-be-selected cell.
1207
+ * @param {number} rowTransformDir Row transformation direction (negative value = up, 0 = none, positive value =
1208
+ * down).
1209
+ * @param {number} colTransformDir Column transformation direction (negative value = up, 0 = none, positive value =
1210
+ * down).
1211
+ */
1212
+ function _onAfterModifyTransformStart(coords, rowTransformDir, colTransformDir) {
1213
+ if (!this.enabled) {
1214
+ return;
1215
+ }
1216
+ const mergedCellAtCoords = this.mergedCellsCollection.get(coords.row, coords.col);
1217
+ if (!mergedCellAtCoords) {
1218
+ return;
1219
+ }
1220
+ const goingDown = rowTransformDir > 0;
1221
+ const goingUp = rowTransformDir < 0;
1222
+ const goingLeft = colTransformDir < 0;
1223
+ const goingRight = colTransformDir > 0;
1224
+ const mergedCellOnBottomEdge = mergedCellAtCoords.row + mergedCellAtCoords.rowspan - 1 === this.hot.countRows() - 1;
1225
+ const mergedCellOnTopEdge = mergedCellAtCoords.row === 0;
1226
+ const mergedCellOnRightEdge = mergedCellAtCoords.col + mergedCellAtCoords.colspan - 1 === this.hot.countCols() - 1;
1227
+ const mergedCellOnLeftEdge = mergedCellAtCoords.col === 0;
1228
+ if (goingDown && mergedCellOnBottomEdge || goingUp && mergedCellOnTopEdge || goingRight && mergedCellOnRightEdge || goingLeft && mergedCellOnLeftEdge) {
1229
+ coords.row = mergedCellAtCoords.row;
1230
+ coords.col = mergedCellAtCoords.col;
1231
+ }
1232
+ }
1374
1233
  /**
1375
1234
  * `afterDrawSelection` hook callback. Used to add the additional class name for the entirely-selected merged cells.
1376
1235
  *