handsontable 0.0.0-next-612100d-20240219 → 0.0.0-next-d96e9b5-20240220

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 (89) hide show
  1. package/3rdparty/walkontable/src/cell/range.d.ts +1 -0
  2. package/3rdparty/walkontable/src/cell/range.js +12 -0
  3. package/3rdparty/walkontable/src/cell/range.mjs +12 -0
  4. package/base.js +2 -2
  5. package/base.mjs +2 -2
  6. package/core/viewportScroll/index.js +4 -1
  7. package/core/viewportScroll/index.mjs +4 -1
  8. package/core/viewportScroll/scrollStrategies/focusScroll.js +15 -0
  9. package/core/viewportScroll/scrollStrategies/focusScroll.mjs +11 -0
  10. package/core.js +14 -0
  11. package/core.mjs +14 -0
  12. package/dist/handsontable.css +2 -2
  13. package/dist/handsontable.full.css +2 -2
  14. package/dist/handsontable.full.js +1606 -1328
  15. package/dist/handsontable.full.min.css +2 -2
  16. package/dist/handsontable.full.min.js +151 -151
  17. package/dist/handsontable.js +1606 -1328
  18. package/dist/handsontable.min.css +2 -2
  19. package/dist/handsontable.min.js +19 -19
  20. package/editorManager.js +12 -8
  21. package/editorManager.mjs +12 -8
  22. package/helpers/mixed.js +1 -1
  23. package/helpers/mixed.mjs +1 -1
  24. package/package.json +1 -1
  25. package/pluginHooks.d.ts +1 -0
  26. package/pluginHooks.js +43 -1
  27. package/pluginHooks.mjs +43 -1
  28. package/plugins/collapsibleColumns/collapsibleColumns.js +7 -1
  29. package/plugins/collapsibleColumns/collapsibleColumns.mjs +7 -1
  30. package/plugins/columnSorting/columnSorting.js +6 -0
  31. package/plugins/columnSorting/columnSorting.mjs +6 -0
  32. package/plugins/contextMenu/menu/defaultShortcutsList.js +26 -10
  33. package/plugins/contextMenu/menu/defaultShortcutsList.mjs +26 -10
  34. package/plugins/mergeCells/calculations/selection.js +1 -70
  35. package/plugins/mergeCells/calculations/selection.mjs +1 -70
  36. package/plugins/mergeCells/contextMenuItem/toggleMerge.js +11 -1
  37. package/plugins/mergeCells/contextMenuItem/toggleMerge.mjs +11 -1
  38. package/plugins/mergeCells/mergeCells.js +182 -207
  39. package/plugins/mergeCells/mergeCells.mjs +182 -207
  40. package/plugins/multiColumnSorting/multiColumnSorting.js +6 -0
  41. package/plugins/multiColumnSorting/multiColumnSorting.mjs +6 -0
  42. package/plugins/nestedHeaders/nestedHeaders.js +1 -0
  43. package/plugins/nestedHeaders/nestedHeaders.mjs +1 -0
  44. package/plugins/nestedRows/nestedRows.js +7 -1
  45. package/plugins/nestedRows/nestedRows.mjs +7 -1
  46. package/renderers/checkboxRenderer/checkboxRenderer.js +4 -4
  47. package/renderers/checkboxRenderer/checkboxRenderer.mjs +4 -4
  48. package/selection/highlight/visualSelection.js +2 -0
  49. package/selection/highlight/visualSelection.mjs +2 -0
  50. package/selection/selection.js +195 -34
  51. package/selection/selection.mjs +194 -33
  52. package/selection/transformation.js +45 -30
  53. package/selection/transformation.mjs +45 -30
  54. package/shortcutContexts/commands/editor/closeAndSave.js +2 -2
  55. package/shortcutContexts/commands/editor/closeAndSave.mjs +2 -2
  56. package/shortcutContexts/commands/editor/open.js +18 -3
  57. package/shortcutContexts/commands/editor/open.mjs +18 -3
  58. package/shortcutContexts/commands/extendCellsSelection/down.js +1 -1
  59. package/shortcutContexts/commands/extendCellsSelection/down.mjs +1 -1
  60. package/shortcutContexts/commands/extendCellsSelection/left.js +1 -1
  61. package/shortcutContexts/commands/extendCellsSelection/left.mjs +1 -1
  62. package/shortcutContexts/commands/extendCellsSelection/right.js +1 -1
  63. package/shortcutContexts/commands/extendCellsSelection/right.mjs +1 -1
  64. package/shortcutContexts/commands/extendCellsSelection/toColumns.js +1 -1
  65. package/shortcutContexts/commands/extendCellsSelection/toColumns.mjs +1 -1
  66. package/shortcutContexts/commands/extendCellsSelection/toMostBottom.js +3 -1
  67. package/shortcutContexts/commands/extendCellsSelection/toMostBottom.mjs +3 -1
  68. package/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.js +9 -3
  69. package/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.mjs +9 -3
  70. package/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.js +10 -3
  71. package/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.mjs +10 -3
  72. package/shortcutContexts/commands/extendCellsSelection/toMostLeft.js +3 -1
  73. package/shortcutContexts/commands/extendCellsSelection/toMostLeft.mjs +3 -1
  74. package/shortcutContexts/commands/extendCellsSelection/toMostRight.js +3 -1
  75. package/shortcutContexts/commands/extendCellsSelection/toMostRight.mjs +3 -1
  76. package/shortcutContexts/commands/extendCellsSelection/toMostTop.js +3 -1
  77. package/shortcutContexts/commands/extendCellsSelection/toMostTop.mjs +3 -1
  78. package/shortcutContexts/commands/extendCellsSelection/toRows.js +1 -1
  79. package/shortcutContexts/commands/extendCellsSelection/toRows.mjs +1 -1
  80. package/shortcutContexts/commands/extendCellsSelection/up.js +1 -1
  81. package/shortcutContexts/commands/extendCellsSelection/up.mjs +1 -1
  82. package/shortcutContexts/commands/moveCellSelection/inlineEnd.js +6 -1
  83. package/shortcutContexts/commands/moveCellSelection/inlineEnd.mjs +6 -1
  84. package/shortcutContexts/commands/moveCellSelection/inlineStart.js +6 -1
  85. package/shortcutContexts/commands/moveCellSelection/inlineStart.mjs +6 -1
  86. package/shortcutContexts/grid.js +2 -2
  87. package/shortcutContexts/grid.mjs +2 -2
  88. package/shortcuts/context.js +2 -1
  89. package/shortcuts/context.mjs +2 -1
@@ -360,6 +360,7 @@ export class NestedHeaders extends BasePlugin {
360
360
  return _classPrivateMethodGet(_this, _onModifyTransformStart, _onModifyTransformStart2).call(_this, ...args);
361
361
  });
362
362
  this.addHook('afterSelection', () => _classPrivateMethodGet(this, _updateFocusHighlightPosition, _updateFocusHighlightPosition2).call(this));
363
+ this.addHook('afterSelectionFocusSet', () => _classPrivateMethodGet(this, _updateFocusHighlightPosition, _updateFocusHighlightPosition2).call(this));
363
364
  this.addHook('beforeViewportScrollHorizontally', function () {
364
365
  for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
365
366
  args[_key8] = arguments[_key8];
@@ -11,6 +11,7 @@ var _contextMenu = _interopRequireDefault(require("./ui/contextMenu"));
11
11
  var _console = require("../../helpers/console");
12
12
  var _data = require("../../helpers/data");
13
13
  var _translations = require("../../translations");
14
+ var _shortcutContexts = require("../../shortcutContexts");
14
15
  var _rowMoveController = _interopRequireDefault(require("./utils/rowMoveController"));
15
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
@@ -400,13 +401,18 @@ class NestedRows extends _base.BasePlugin {
400
401
  this.collapsingUI.collapseChildren(row);
401
402
  }
402
403
  }
404
+
405
+ // prevent default Enter behavior (move to the next row within a selection range)
406
+ return false;
403
407
  },
404
408
  runOnlyIf: () => {
405
409
  var _this$hot$getSelected;
406
410
  const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
407
411
  return highlight && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
408
412
  },
409
- group: SHORTCUTS_GROUP
413
+ group: SHORTCUTS_GROUP,
414
+ relativeToGroup: _shortcutContexts.EDITOR_EDIT_GROUP,
415
+ position: 'before'
410
416
  });
411
417
  }
412
418
 
@@ -20,6 +20,7 @@ import ContextMenuUI from "./ui/contextMenu.mjs";
20
20
  import { error } from "../../helpers/console.mjs";
21
21
  import { isArrayOfObjects } from "../../helpers/data.mjs";
22
22
  import { TrimmingMap } from "../../translations/index.mjs";
23
+ import { EDITOR_EDIT_GROUP as SHORTCUTS_GROUP_EDITOR } from "../../shortcutContexts/index.mjs";
23
24
  import RowMoveController from "./utils/rowMoveController.mjs";
24
25
  export const PLUGIN_KEY = 'nestedRows';
25
26
  export const PLUGIN_PRIORITY = 300;
@@ -396,13 +397,18 @@ export class NestedRows extends BasePlugin {
396
397
  this.collapsingUI.collapseChildren(row);
397
398
  }
398
399
  }
400
+
401
+ // prevent default Enter behavior (move to the next row within a selection range)
402
+ return false;
399
403
  },
400
404
  runOnlyIf: () => {
401
405
  var _this$hot$getSelected;
402
406
  const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
403
407
  return highlight && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
404
408
  },
405
- group: SHORTCUTS_GROUP
409
+ group: SHORTCUTS_GROUP,
410
+ relativeToGroup: SHORTCUTS_GROUP_EDITOR,
411
+ position: 'before'
406
412
  });
407
413
  }
408
414
 
@@ -139,7 +139,9 @@ function checkboxRenderer(hotInstance, TD, row, col, prop, value, cellProperties
139
139
  const shortcutManager = hotInstance.getShortcutManager();
140
140
  const gridContext = shortcutManager.getContext('grid');
141
141
  const config = {
142
- group: SHORTCUTS_GROUP
142
+ group: SHORTCUTS_GROUP,
143
+ relativeToGroup: _shortcutContexts.EDITOR_EDIT_GROUP,
144
+ position: 'before'
143
145
  };
144
146
  gridContext.addShortcuts([{
145
147
  keys: [['space']],
@@ -159,9 +161,7 @@ function checkboxRenderer(hotInstance, TD, row, col, prop, value, cellProperties
159
161
  callback: () => {
160
162
  changeSelectedCheckboxesState(true);
161
163
  return !areSelectedCheckboxCells(); // False blocks next action associated with the keyboard shortcut.
162
- },
163
- relativeToGroup: _shortcutContexts.EDITOR_EDIT_GROUP,
164
- position: 'before'
164
+ }
165
165
  }], config);
166
166
  }
167
167
 
@@ -134,7 +134,9 @@ export function checkboxRenderer(hotInstance, TD, row, col, prop, value, cellPro
134
134
  const shortcutManager = hotInstance.getShortcutManager();
135
135
  const gridContext = shortcutManager.getContext('grid');
136
136
  const config = {
137
- group: SHORTCUTS_GROUP
137
+ group: SHORTCUTS_GROUP,
138
+ relativeToGroup: SHORTCUTS_GROUP_EDITOR,
139
+ position: 'before'
138
140
  };
139
141
  gridContext.addShortcuts([{
140
142
  keys: [['space']],
@@ -154,9 +156,7 @@ export function checkboxRenderer(hotInstance, TD, row, col, prop, value, cellPro
154
156
  callback: () => {
155
157
  changeSelectedCheckboxesState(true);
156
158
  return !areSelectedCheckboxCells(); // False blocks next action associated with the keyboard shortcut.
157
- },
158
- relativeToGroup: SHORTCUTS_GROUP_EDITOR,
159
- position: 'before'
159
+ }
160
160
  }], config);
161
161
  }
162
162
 
@@ -170,11 +170,13 @@ class VisualSelection extends _src.Selection {
170
170
  this.cellRange = this.settings.createCellRange(cellCoordsRenderable);
171
171
  }
172
172
 
173
+ // TODO
173
174
  // We set new highlight as it might change (for example, when showing/hiding some cells from the broader selection range)
174
175
  // TODO: It is also handled by the `MergeCells` plugin while adjusting already modified coordinates. Should it?
175
176
  broaderCellRange.setHighlight(currentHighlight);
176
177
  }
177
178
 
179
+ // TODO
178
180
  // Sync the highlight coords from the visual selection layer with logical coords.
179
181
  if (this.settings.selectionType === 'focus' && renderableHighlight !== null && cellCoordsVisual === null) {
180
182
  broaderCellRange.setHighlight(this.visualCellRange.highlight);
@@ -167,11 +167,13 @@ class VisualSelection extends Selection {
167
167
  this.cellRange = this.settings.createCellRange(cellCoordsRenderable);
168
168
  }
169
169
 
170
+ // TODO
170
171
  // We set new highlight as it might change (for example, when showing/hiding some cells from the broader selection range)
171
172
  // TODO: It is also handled by the `MergeCells` plugin while adjusting already modified coordinates. Should it?
172
173
  broaderCellRange.setHighlight(currentHighlight);
173
174
  }
174
175
 
176
+ // TODO
175
177
  // Sync the highlight coords from the visual selection layer with logical coords.
176
178
  if (this.settings.selectionType === 'focus' && renderableHighlight !== null && cellCoordsVisual === null) {
177
179
  broaderCellRange.setHighlight(this.visualCellRange.highlight);
@@ -9,7 +9,7 @@ var _mixed = require("./../helpers/mixed");
9
9
  var _number = require("./../helpers/number");
10
10
  var _array = require("./../helpers/array");
11
11
  var _localHooks = _interopRequireDefault(require("./../mixins/localHooks"));
12
- var _transformation = _interopRequireDefault(require("./transformation"));
12
+ var _transformation2 = _interopRequireDefault(require("./transformation"));
13
13
  var _utils = require("./utils");
14
14
  var _templateLiteralTag = require("./../helpers/templateLiteralTag");
15
15
  var _a11y = require("../helpers/a11y");
@@ -30,6 +30,9 @@ function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.
30
30
  * @class Selection
31
31
  * @util
32
32
  */
33
+ var _transformation = /*#__PURE__*/new WeakMap();
34
+ var _focusTransformation = /*#__PURE__*/new WeakMap();
35
+ var _isFocusSelectionChanged = /*#__PURE__*/new WeakMap();
33
36
  var _disableHeadersHighlight = /*#__PURE__*/new WeakMap();
34
37
  var _selectionSource = /*#__PURE__*/new WeakMap();
35
38
  var _expectedLayersCount = /*#__PURE__*/new WeakMap();
@@ -69,11 +72,23 @@ class Selection {
69
72
  */
70
73
  _defineProperty(this, "highlight", void 0);
71
74
  /**
72
- * The module for modifying coordinates.
75
+ * The module for modifying coordinates of the start and end selection.
73
76
  *
74
77
  * @type {Transformation}
75
78
  */
76
- _defineProperty(this, "transformation", void 0);
79
+ _classPrivateFieldInitSpec(this, _transformation, {
80
+ writable: true,
81
+ value: void 0
82
+ });
83
+ /**
84
+ * The module for modifying coordinates of the focus selection.
85
+ *
86
+ * @type {Transformation}
87
+ */
88
+ _classPrivateFieldInitSpec(this, _focusTransformation, {
89
+ writable: true,
90
+ value: void 0
91
+ });
77
92
  /**
78
93
  * The collection of the selection layer levels where the whole row was selected using the row header or
79
94
  * the corner header.
@@ -88,6 +103,15 @@ class Selection {
88
103
  * @type {Set<number>}
89
104
  */
90
105
  _defineProperty(this, "selectedByColumnHeader", new Set());
106
+ /**
107
+ * The flag which determines if the focus selection was changed.
108
+ *
109
+ * @type {boolean}
110
+ */
111
+ _classPrivateFieldInitSpec(this, _isFocusSelectionChanged, {
112
+ writable: true,
113
+ value: false
114
+ });
91
115
  /**
92
116
  * When sets disable highlighting the headers even when the logical coordinates points on them.
93
117
  *
@@ -138,71 +162,100 @@ class Selection {
138
162
  createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),
139
163
  createCellRange: (highlight, from, to) => this.tableProps.createCellRange(highlight, from, to)
140
164
  });
141
- this.transformation = new _transformation.default(this.selectedRange, {
165
+ _classPrivateFieldSet(this, _transformation, new _transformation2.default(this.selectedRange, {
142
166
  rowIndexMapper: this.tableProps.rowIndexMapper,
143
167
  columnIndexMapper: this.tableProps.columnIndexMapper,
144
168
  countRenderableRows: () => this.tableProps.countRenderableRows(),
145
169
  countRenderableColumns: () => this.tableProps.countRenderableColumns(),
146
- countRowHeaders: () => this.tableProps.countRowHeaders(),
147
- countColHeaders: () => this.tableProps.countColHeaders(),
148
170
  visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),
149
171
  renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),
150
172
  createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),
151
- navigableHeaders: () => settings.navigableHeaders,
152
173
  fixedRowsBottom: () => settings.fixedRowsBottom,
153
174
  minSpareRows: () => settings.minSpareRows,
154
175
  minSpareCols: () => settings.minSpareCols,
155
176
  autoWrapRow: () => settings.autoWrapRow,
156
177
  autoWrapCol: () => settings.autoWrapCol
157
- });
158
- this.transformation.addLocalHook('beforeTransformStart', function () {
178
+ }));
179
+ _classPrivateFieldSet(this, _focusTransformation, new _transformation2.default(this.selectedRange, {
180
+ rowIndexMapper: this.tableProps.rowIndexMapper,
181
+ columnIndexMapper: this.tableProps.columnIndexMapper,
182
+ countRenderableRows: () => {
183
+ const range = this.selectedRange.current();
184
+ return this.tableProps.countRenderableRowsInRange(0, range.getOuterBottomEndCorner().row);
185
+ },
186
+ countRenderableColumns: () => {
187
+ const range = this.selectedRange.current();
188
+ return this.tableProps.countRenderableColumnsInRange(0, range.getOuterBottomEndCorner().col);
189
+ },
190
+ visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),
191
+ renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),
192
+ createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),
193
+ fixedRowsBottom: () => 0,
194
+ minSpareRows: () => 0,
195
+ minSpareCols: () => 0,
196
+ autoWrapRow: () => true,
197
+ autoWrapCol: () => true
198
+ }));
199
+ _classPrivateFieldGet(this, _transformation).addLocalHook('beforeTransformStart', function () {
159
200
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
160
201
  args[_key] = arguments[_key];
161
202
  }
162
203
  return _this.runLocalHooks('beforeModifyTransformStart', ...args);
163
204
  });
164
- this.transformation.addLocalHook('afterTransformStart', function () {
205
+ _classPrivateFieldGet(this, _transformation).addLocalHook('afterTransformStart', function () {
165
206
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
166
207
  args[_key2] = arguments[_key2];
167
208
  }
168
209
  return _this.runLocalHooks('afterModifyTransformStart', ...args);
169
210
  });
170
- this.transformation.addLocalHook('beforeTransformEnd', function () {
211
+ _classPrivateFieldGet(this, _transformation).addLocalHook('beforeTransformEnd', function () {
171
212
  for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
172
213
  args[_key3] = arguments[_key3];
173
214
  }
174
215
  return _this.runLocalHooks('beforeModifyTransformEnd', ...args);
175
216
  });
176
- this.transformation.addLocalHook('afterTransformEnd', function () {
217
+ _classPrivateFieldGet(this, _transformation).addLocalHook('afterTransformEnd', function () {
177
218
  for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
178
219
  args[_key4] = arguments[_key4];
179
220
  }
180
221
  return _this.runLocalHooks('afterModifyTransformEnd', ...args);
181
222
  });
182
- this.transformation.addLocalHook('insertRowRequire', function () {
223
+ _classPrivateFieldGet(this, _transformation).addLocalHook('insertRowRequire', function () {
183
224
  for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
184
225
  args[_key5] = arguments[_key5];
185
226
  }
186
227
  return _this.runLocalHooks('insertRowRequire', ...args);
187
228
  });
188
- this.transformation.addLocalHook('insertColRequire', function () {
229
+ _classPrivateFieldGet(this, _transformation).addLocalHook('insertColRequire', function () {
189
230
  for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
190
231
  args[_key6] = arguments[_key6];
191
232
  }
192
233
  return _this.runLocalHooks('insertColRequire', ...args);
193
234
  });
194
- this.transformation.addLocalHook('beforeRowWrap', function () {
235
+ _classPrivateFieldGet(this, _transformation).addLocalHook('beforeRowWrap', function () {
195
236
  for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
196
237
  args[_key7] = arguments[_key7];
197
238
  }
198
239
  return _this.runLocalHooks('beforeRowWrap', ...args);
199
240
  });
200
- this.transformation.addLocalHook('beforeColumnWrap', function () {
241
+ _classPrivateFieldGet(this, _transformation).addLocalHook('beforeColumnWrap', function () {
201
242
  for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
202
243
  args[_key8] = arguments[_key8];
203
244
  }
204
245
  return _this.runLocalHooks('beforeColumnWrap', ...args);
205
246
  });
247
+ _classPrivateFieldGet(this, _focusTransformation).addLocalHook('beforeTransformStart', function () {
248
+ for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
249
+ args[_key9] = arguments[_key9];
250
+ }
251
+ return _this.runLocalHooks('beforeModifyTransformStart', ...args);
252
+ });
253
+ _classPrivateFieldGet(this, _focusTransformation).addLocalHook('afterTransformStart', function () {
254
+ for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
255
+ args[_key10] = arguments[_key10];
256
+ }
257
+ return _this.runLocalHooks('afterModifyTransformStart', ...args);
258
+ });
206
259
  }
207
260
 
208
261
  /**
@@ -293,6 +346,7 @@ class Selection {
293
346
  // We are creating copy. We would like to modify just the start of the selection by below hook. Then original coords
294
347
  // should be handled by next methods.
295
348
  const coordsClone = coords.clone();
349
+ _classPrivateFieldSet(this, _isFocusSelectionChanged, false);
296
350
  this.runLocalHooks(`beforeSetRangeStart${fragment ? 'Only' : ''}`, coordsClone);
297
351
  if (!isMultipleMode || isMultipleMode && !isMultipleSelection && (0, _mixed.isUndefined)(multipleSelection)) {
298
352
  this.selectedRange.clear();
@@ -350,7 +404,20 @@ class Selection {
350
404
  cellRange.setFrom(cellRange.highlight);
351
405
  cellRange.setTo(cellRange.highlight);
352
406
  } else {
407
+ const horizontalDir = cellRange.getHorizontalDirection();
408
+ const verticalDir = cellRange.getVerticalDirection();
409
+ const isMultiple = this.isMultiple();
353
410
  cellRange.setTo(coordsClone);
411
+ if (isMultiple && horizontalDir !== cellRange.getHorizontalDirection()) {
412
+ cellRange.from.assign({
413
+ col: cellRange.highlight.col
414
+ });
415
+ }
416
+ if (isMultiple && verticalDir !== cellRange.getVerticalDirection()) {
417
+ cellRange.from.assign({
418
+ row: cellRange.highlight.row
419
+ });
420
+ }
354
421
  }
355
422
 
356
423
  // Prevent creating "area" selection that overlaps headers.
@@ -360,11 +427,7 @@ class Selection {
360
427
  }
361
428
  }
362
429
  this.runLocalHooks('beforeHighlightSet');
363
- const focusHighlight = this.highlight.getFocus();
364
- focusHighlight.clear();
365
- if (this.highlight.isEnabledFor(_highlight.FOCUS_TYPE, cellRange.highlight)) {
366
- focusHighlight.add(this.selectedRange.current().highlight).commit().syncWith(cellRange);
367
- }
430
+ this.setRangeFocus(this.selectedRange.current().highlight);
368
431
  const layerLevel = this.getLayerLevel();
369
432
 
370
433
  // If the next layer level is lower than previous then clear all area and header highlights. This is the
@@ -452,15 +515,28 @@ class Selection {
452
515
  }
453
516
 
454
517
  /**
455
- * Returns information if we have a multiselection. This method check multiselection only on the latest layer of
456
- * the selection.
518
+ * Sets the selection focus position at the specified coordinates.
457
519
  *
458
- * @returns {boolean}
520
+ * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.
459
521
  */
460
- isMultiple() {
461
- const isMultipleListener = (0, _object.createObjectPropListener)(!this.selectedRange.current().isSingle());
462
- this.runLocalHooks('afterIsMultipleSelection', isMultipleListener);
463
- return isMultipleListener.value;
522
+ setRangeFocus(coords) {
523
+ if (this.selectedRange.isEmpty()) {
524
+ return;
525
+ }
526
+ const cellRange = this.selectedRange.current();
527
+ const focusHighlight = this.highlight.getFocus();
528
+ focusHighlight.clear();
529
+ cellRange.setHighlight(coords);
530
+ if (!this.inProgress) {
531
+ this.runLocalHooks('beforeHighlightSet');
532
+ }
533
+ if (this.highlight.isEnabledFor(_highlight.FOCUS_TYPE, cellRange.highlight)) {
534
+ focusHighlight.add(cellRange.highlight).commit().syncWith(cellRange);
535
+ }
536
+ if (!this.inProgress) {
537
+ _classPrivateFieldSet(this, _isFocusSelectionChanged, true);
538
+ this.runLocalHooks('afterSetFocus', cellRange.highlight);
539
+ }
464
540
  }
465
541
 
466
542
  /**
@@ -473,7 +549,13 @@ class Selection {
473
549
  */
474
550
  transformStart(rowDelta, colDelta) {
475
551
  let createMissingRecords = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
476
- this.setRangeStart(this.transformation.transformStart(rowDelta, colDelta, createMissingRecords));
552
+ if (this.settings.navigableHeaders) {
553
+ _classPrivateFieldGet(this, _transformation).setOffsetSize({
554
+ x: this.tableProps.countRowHeaders(),
555
+ y: this.tableProps.countColHeaders()
556
+ });
557
+ }
558
+ this.setRangeStart(_classPrivateFieldGet(this, _transformation).transformStart(rowDelta, colDelta, createMissingRecords));
477
559
  }
478
560
 
479
561
  /**
@@ -483,7 +565,44 @@ class Selection {
483
565
  * @param {number} colDelta Columns number to move, value can be passed as negative number.
484
566
  */
485
567
  transformEnd(rowDelta, colDelta) {
486
- this.setRangeEnd(this.transformation.transformEnd(rowDelta, colDelta));
568
+ if (this.settings.navigableHeaders) {
569
+ _classPrivateFieldGet(this, _transformation).setOffsetSize({
570
+ x: this.tableProps.countRowHeaders(),
571
+ y: this.tableProps.countColHeaders()
572
+ });
573
+ }
574
+ this.setRangeEnd(_classPrivateFieldGet(this, _transformation).transformEnd(rowDelta, colDelta));
575
+ }
576
+
577
+ /**
578
+ * Transforms the focus cell selection relative to the current focus position.
579
+ *
580
+ * @param {number} rowDelta Rows number to move, value can be passed as negative number.
581
+ * @param {number} colDelta Columns number to move, value can be passed as negative number.
582
+ */
583
+ transformFocus(rowDelta, colDelta) {
584
+ const range = this.selectedRange.current();
585
+ const {
586
+ row,
587
+ col
588
+ } = range.getOuterTopStartCorner();
589
+ const columnsInRange = this.tableProps.countRenderableColumnsInRange(0, col - 1);
590
+ const rowsInRange = this.tableProps.countRenderableRowsInRange(0, row - 1);
591
+ if (range.highlight.isHeader()) {
592
+ // for header focus selection calculate the new coords based on the selection including headers
593
+ _classPrivateFieldGet(this, _focusTransformation).setOffsetSize({
594
+ x: col < 0 ? Math.abs(col) : -columnsInRange,
595
+ y: row < 0 ? Math.abs(row) : -rowsInRange
596
+ });
597
+ } else {
598
+ // for focus selection in cells calculate the new coords only based on the selected cells
599
+ _classPrivateFieldGet(this, _focusTransformation).setOffsetSize({
600
+ x: col < 0 ? 0 : -columnsInRange,
601
+ y: row < 0 ? 0 : -rowsInRange
602
+ });
603
+ }
604
+ const focusCoords = _classPrivateFieldGet(this, _focusTransformation).transformStart(rowDelta, colDelta);
605
+ this.setRangeFocus(focusCoords.normalize());
487
606
  }
488
607
 
489
608
  /**
@@ -504,6 +623,30 @@ class Selection {
504
623
  return !this.selectedRange.isEmpty();
505
624
  }
506
625
 
626
+ /**
627
+ * Returns information if we have a multi-selection. This method check multi-selection only on the latest layer of
628
+ * the selection.
629
+ *
630
+ * @returns {boolean}
631
+ */
632
+ isMultiple() {
633
+ if (!this.isSelected()) {
634
+ return false;
635
+ }
636
+ const isMultipleListener = (0, _object.createObjectPropListener)(!this.selectedRange.current().isSingle());
637
+ this.runLocalHooks('afterIsMultipleSelection', isMultipleListener);
638
+ return isMultipleListener.value;
639
+ }
640
+
641
+ /**
642
+ * Checks if the last selection involves changing the focus cell position only.
643
+ *
644
+ * @returns {boolean}
645
+ */
646
+ isFocusSelectionChanged() {
647
+ return this.isSelected() && _classPrivateFieldGet(this, _isFocusSelectionChanged);
648
+ }
649
+
507
650
  /**
508
651
  * Returns `true` if the selection was applied by clicking to the row header. If the `layerLevel`
509
652
  * argument is passed then only that layer will be checked. Otherwise, it checks if any row header
@@ -809,11 +952,20 @@ class Selection {
809
952
  countColHeaders
810
953
  });
811
954
  if (isValid) {
812
- const fromRow = countColHeaders === 0 ? 0 : (0, _number.clamp)(focusPosition, columnHeaderLastIndex, -1);
955
+ let highlightRow = 0;
956
+ let highlightColumn = 0;
957
+ if (Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {
958
+ highlightRow = (0, _number.clamp)(focusPosition.row, columnHeaderLastIndex, countRows - 1);
959
+ highlightColumn = (0, _number.clamp)(focusPosition.col, Math.min(start, end), Math.max(start, end));
960
+ } else {
961
+ highlightRow = (0, _number.clamp)(focusPosition, columnHeaderLastIndex, countRows - 1);
962
+ highlightColumn = start;
963
+ }
964
+ const highlight = this.tableProps.createCellCoords(highlightRow, highlightColumn);
965
+ const fromRow = countColHeaders === 0 ? 0 : (0, _number.clamp)(highlight.row, columnHeaderLastIndex, -1);
813
966
  const toRow = countRows - 1;
814
967
  const from = this.tableProps.createCellCoords(fromRow, start);
815
968
  const to = this.tableProps.createCellCoords(toRow, end);
816
- const highlight = this.tableProps.createCellCoords((0, _number.clamp)(focusPosition, columnHeaderLastIndex, countRows - 1), start);
817
969
  this.runLocalHooks('beforeSelectColumns', from, to, highlight);
818
970
 
819
971
  // disallow modifying row axis for that hooks
@@ -854,11 +1006,20 @@ class Selection {
854
1006
  countColHeaders: 0
855
1007
  });
856
1008
  if (isValid) {
857
- const fromColumn = countRowHeaders === 0 ? 0 : (0, _number.clamp)(focusPosition, rowHeaderLastIndex, -1);
1009
+ let highlightRow = 0;
1010
+ let highlightColumn = 0;
1011
+ if (Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {
1012
+ highlightRow = (0, _number.clamp)(focusPosition.row, Math.min(startRow, endRow), Math.max(startRow, endRow));
1013
+ highlightColumn = (0, _number.clamp)(focusPosition.col, rowHeaderLastIndex, countCols - 1);
1014
+ } else {
1015
+ highlightRow = startRow;
1016
+ highlightColumn = (0, _number.clamp)(focusPosition, rowHeaderLastIndex, countCols - 1);
1017
+ }
1018
+ const highlight = this.tableProps.createCellCoords(highlightRow, highlightColumn);
1019
+ const fromColumn = countRowHeaders === 0 ? 0 : (0, _number.clamp)(highlight.col, rowHeaderLastIndex, -1);
858
1020
  const toColumn = countCols - 1;
859
1021
  const from = this.tableProps.createCellCoords(startRow, fromColumn);
860
1022
  const to = this.tableProps.createCellCoords(endRow, toColumn);
861
- const highlight = this.tableProps.createCellCoords(startRow, (0, _number.clamp)(focusPosition, rowHeaderLastIndex, countCols - 1));
862
1023
  this.runLocalHooks('beforeSelectRows', from, to, highlight);
863
1024
 
864
1025
  // disallow modifying column axis for that hooks