handsontable 0.0.0-next-8dc7078-20240322 → 0.0.0-next-28fc088-20240325

Sign up to get free protection for your applications and to get access to all the features.

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 +2 -1
  2. package/3rdparty/walkontable/src/cell/range.js +22 -5
  3. package/3rdparty/walkontable/src/cell/range.mjs +22 -5
  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.d.ts +4 -3
  11. package/core.js +76 -21
  12. package/core.mjs +76 -21
  13. package/dist/handsontable.css +2 -2
  14. package/dist/handsontable.full.css +2 -2
  15. package/dist/handsontable.full.js +2649 -1389
  16. package/dist/handsontable.full.min.css +2 -2
  17. package/dist/handsontable.full.min.js +71 -71
  18. package/dist/handsontable.js +2653 -1393
  19. package/dist/handsontable.min.css +2 -2
  20. package/dist/handsontable.min.js +19 -19
  21. package/editorManager.js +12 -8
  22. package/editorManager.mjs +12 -8
  23. package/focusManager.js +7 -1
  24. package/focusManager.mjs +7 -1
  25. package/helpers/mixed.js +1 -1
  26. package/helpers/mixed.mjs +1 -1
  27. package/package.json +1 -1
  28. package/pluginHooks.d.ts +4 -0
  29. package/pluginHooks.js +98 -37
  30. package/pluginHooks.mjs +98 -37
  31. package/plugins/collapsibleColumns/collapsibleColumns.js +9 -3
  32. package/plugins/collapsibleColumns/collapsibleColumns.mjs +9 -3
  33. package/plugins/columnSorting/columnSorting.js +8 -2
  34. package/plugins/columnSorting/columnSorting.mjs +8 -2
  35. package/plugins/contextMenu/menu/defaultShortcutsList.js +26 -10
  36. package/plugins/contextMenu/menu/defaultShortcutsList.mjs +26 -10
  37. package/plugins/mergeCells/calculations/selection.js +1 -70
  38. package/plugins/mergeCells/calculations/selection.mjs +1 -70
  39. package/plugins/mergeCells/cellsCollection.js +116 -0
  40. package/plugins/mergeCells/cellsCollection.mjs +116 -0
  41. package/plugins/mergeCells/contextMenuItem/toggleMerge.js +11 -1
  42. package/plugins/mergeCells/contextMenuItem/toggleMerge.mjs +11 -1
  43. package/plugins/mergeCells/focusOrder.js +305 -0
  44. package/plugins/mergeCells/focusOrder.mjs +300 -0
  45. package/plugins/mergeCells/mergeCells.js +336 -192
  46. package/plugins/mergeCells/mergeCells.mjs +336 -192
  47. package/plugins/multiColumnSorting/multiColumnSorting.js +8 -2
  48. package/plugins/multiColumnSorting/multiColumnSorting.mjs +8 -2
  49. package/plugins/nestedHeaders/nestedHeaders.js +1 -0
  50. package/plugins/nestedHeaders/nestedHeaders.mjs +1 -0
  51. package/plugins/nestedRows/nestedRows.js +9 -3
  52. package/plugins/nestedRows/nestedRows.mjs +9 -3
  53. package/renderers/checkboxRenderer/checkboxRenderer.js +8 -5
  54. package/renderers/checkboxRenderer/checkboxRenderer.mjs +8 -5
  55. package/selection/highlight/visualSelection.js +2 -0
  56. package/selection/highlight/visualSelection.mjs +2 -0
  57. package/selection/selection.js +209 -40
  58. package/selection/selection.mjs +208 -39
  59. package/selection/transformation.js +83 -32
  60. package/selection/transformation.mjs +83 -32
  61. package/shortcutContexts/commands/editor/closeAndSave.js +2 -2
  62. package/shortcutContexts/commands/editor/closeAndSave.mjs +2 -2
  63. package/shortcutContexts/commands/editor/open.js +18 -3
  64. package/shortcutContexts/commands/editor/open.mjs +18 -3
  65. package/shortcutContexts/commands/extendCellsSelection/down.js +1 -1
  66. package/shortcutContexts/commands/extendCellsSelection/down.mjs +1 -1
  67. package/shortcutContexts/commands/extendCellsSelection/left.js +1 -1
  68. package/shortcutContexts/commands/extendCellsSelection/left.mjs +1 -1
  69. package/shortcutContexts/commands/extendCellsSelection/right.js +1 -1
  70. package/shortcutContexts/commands/extendCellsSelection/right.mjs +1 -1
  71. package/shortcutContexts/commands/extendCellsSelection/toColumns.js +1 -1
  72. package/shortcutContexts/commands/extendCellsSelection/toColumns.mjs +1 -1
  73. package/shortcutContexts/commands/extendCellsSelection/toMostBottom.js +3 -1
  74. package/shortcutContexts/commands/extendCellsSelection/toMostBottom.mjs +3 -1
  75. package/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.js +9 -3
  76. package/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.mjs +9 -3
  77. package/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.js +10 -3
  78. package/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.mjs +10 -3
  79. package/shortcutContexts/commands/extendCellsSelection/toMostLeft.js +3 -1
  80. package/shortcutContexts/commands/extendCellsSelection/toMostLeft.mjs +3 -1
  81. package/shortcutContexts/commands/extendCellsSelection/toMostRight.js +3 -1
  82. package/shortcutContexts/commands/extendCellsSelection/toMostRight.mjs +3 -1
  83. package/shortcutContexts/commands/extendCellsSelection/toMostTop.js +3 -1
  84. package/shortcutContexts/commands/extendCellsSelection/toMostTop.mjs +3 -1
  85. package/shortcutContexts/commands/extendCellsSelection/toRows.js +1 -1
  86. package/shortcutContexts/commands/extendCellsSelection/toRows.mjs +1 -1
  87. package/shortcutContexts/commands/extendCellsSelection/up.js +1 -1
  88. package/shortcutContexts/commands/extendCellsSelection/up.mjs +1 -1
  89. package/shortcutContexts/commands/moveCellSelection/inlineEnd.js +6 -1
  90. package/shortcutContexts/commands/moveCellSelection/inlineEnd.mjs +6 -1
  91. package/shortcutContexts/commands/moveCellSelection/inlineStart.js +6 -1
  92. package/shortcutContexts/commands/moveCellSelection/inlineStart.mjs +6 -1
  93. package/shortcutContexts/grid.js +2 -2
  94. package/shortcutContexts/grid.mjs +2 -2
  95. package/shortcuts/context.js +2 -1
  96. package/shortcuts/context.mjs +2 -1
  97. package/utils/dataStructures/linkedList.js +6 -1
  98. package/utils/dataStructures/linkedList.mjs +6 -1
@@ -9,6 +9,7 @@ var _element = require("../../helpers/dom/element");
9
9
  var _rootComparator = require("./rootComparator");
10
10
  var _utils2 = require("./utils");
11
11
  var _domHelpers = require("./domHelpers");
12
+ var _shortcutContexts = require("../../shortcutContexts");
12
13
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
13
14
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
14
15
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
@@ -130,12 +131,17 @@ class MultiColumnSorting extends _columnSorting.ColumnSorting {
130
131
  if (highlight.row === -1 && highlight.col >= 0) {
131
132
  this.sort(this.getNextSortConfig(highlight.col, _columnSorting.APPEND_COLUMN_CONFIG_STRATEGY));
132
133
  }
134
+
135
+ // prevent default Enter behavior (move to the next row within a selection range)
136
+ return false;
133
137
  },
134
138
  runOnlyIf: () => {
135
- var _this$hot$getSelected;
139
+ var _this$hot$getSelected, _this$hot$getSelected2;
136
140
  const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
137
- return highlight && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
141
+ return highlight && ((_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.isSingle()) && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
138
142
  },
143
+ relativeToGroup: _shortcutContexts.EDITOR_EDIT_GROUP,
144
+ position: 'before',
139
145
  group: SHORTCUTS_GROUP
140
146
  });
141
147
  }
@@ -9,6 +9,7 @@ import { addClass, removeClass } from "../../helpers/dom/element.mjs";
9
9
  import { rootComparator } from "./rootComparator.mjs";
10
10
  import { warnAboutPluginsConflict } from "./utils.mjs";
11
11
  import { getClassesToAdd, getClassesToRemove } from "./domHelpers.mjs";
12
+ import { EDITOR_EDIT_GROUP as SHORTCUTS_GROUP_EDITOR } from "../../shortcutContexts/index.mjs";
12
13
  export const PLUGIN_KEY = 'multiColumnSorting';
13
14
  export const PLUGIN_PRIORITY = 170;
14
15
  const CONFLICTED_PLUGIN_KEY = 'columnSorting';
@@ -127,12 +128,17 @@ export class MultiColumnSorting extends ColumnSorting {
127
128
  if (highlight.row === -1 && highlight.col >= 0) {
128
129
  this.sort(this.getNextSortConfig(highlight.col, APPEND_COLUMN_CONFIG_STRATEGY));
129
130
  }
131
+
132
+ // prevent default Enter behavior (move to the next row within a selection range)
133
+ return false;
130
134
  },
131
135
  runOnlyIf: () => {
132
- var _this$hot$getSelected;
136
+ var _this$hot$getSelected, _this$hot$getSelected2;
133
137
  const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
134
- return highlight && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
138
+ return highlight && ((_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.isSingle()) && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
135
139
  },
140
+ relativeToGroup: SHORTCUTS_GROUP_EDITOR,
141
+ position: 'before',
136
142
  group: SHORTCUTS_GROUP
137
143
  });
138
144
  }
@@ -198,6 +198,7 @@ class NestedHeaders extends _base.BasePlugin {
198
198
  return _assertClassBrand(_NestedHeaders_brand, _this, _onModifyTransformStart).call(_this, ...args);
199
199
  });
200
200
  this.addHook('afterSelection', () => _assertClassBrand(_NestedHeaders_brand, this, _updateFocusHighlightPosition).call(this));
201
+ this.addHook('afterSelectionFocusSet', () => _assertClassBrand(_NestedHeaders_brand, this, _updateFocusHighlightPosition).call(this));
201
202
  this.addHook('beforeViewportScrollHorizontally', function () {
202
203
  for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
203
204
  args[_key8] = arguments[_key8];
@@ -194,6 +194,7 @@ export class NestedHeaders extends BasePlugin {
194
194
  return _assertClassBrand(_NestedHeaders_brand, _this, _onModifyTransformStart).call(_this, ...args);
195
195
  });
196
196
  this.addHook('afterSelection', () => _assertClassBrand(_NestedHeaders_brand, this, _updateFocusHighlightPosition).call(this));
197
+ this.addHook('afterSelectionFocusSet', () => _assertClassBrand(_NestedHeaders_brand, this, _updateFocusHighlightPosition).call(this));
197
198
  this.addHook('beforeViewportScrollHorizontally', function () {
198
199
  for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
199
200
  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); }
@@ -276,13 +277,18 @@ class NestedRows extends _base.BasePlugin {
276
277
  this.collapsingUI.collapseChildren(row);
277
278
  }
278
279
  }
280
+
281
+ // prevent default Enter behavior (move to the next row within a selection range)
282
+ return false;
279
283
  },
280
284
  runOnlyIf: () => {
281
- var _this$hot$getSelected;
285
+ var _this$hot$getSelected, _this$hot$getSelected2;
282
286
  const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
283
- return highlight && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
287
+ return highlight && ((_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.isSingle()) && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
284
288
  },
285
- group: SHORTCUTS_GROUP
289
+ group: SHORTCUTS_GROUP,
290
+ relativeToGroup: _shortcutContexts.EDITOR_EDIT_GROUP,
291
+ position: 'before'
286
292
  });
287
293
  }
288
294
 
@@ -17,6 +17,7 @@ import ContextMenuUI from "./ui/contextMenu.mjs";
17
17
  import { error } from "../../helpers/console.mjs";
18
18
  import { isArrayOfObjects } from "../../helpers/data.mjs";
19
19
  import { TrimmingMap } from "../../translations/index.mjs";
20
+ import { EDITOR_EDIT_GROUP as SHORTCUTS_GROUP_EDITOR } from "../../shortcutContexts/index.mjs";
20
21
  import RowMoveController from "./utils/rowMoveController.mjs";
21
22
  export const PLUGIN_KEY = 'nestedRows';
22
23
  export const PLUGIN_PRIORITY = 300;
@@ -272,13 +273,18 @@ export class NestedRows extends BasePlugin {
272
273
  this.collapsingUI.collapseChildren(row);
273
274
  }
274
275
  }
276
+
277
+ // prevent default Enter behavior (move to the next row within a selection range)
278
+ return false;
275
279
  },
276
280
  runOnlyIf: () => {
277
- var _this$hot$getSelected;
281
+ var _this$hot$getSelected, _this$hot$getSelected2;
278
282
  const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
279
- return highlight && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
283
+ return highlight && ((_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.isSingle()) && this.hot.selection.isCellVisible(highlight) && highlight.isHeader();
280
284
  },
281
- group: SHORTCUTS_GROUP
285
+ group: SHORTCUTS_GROUP,
286
+ relativeToGroup: SHORTCUTS_GROUP_EDITOR,
287
+ position: 'before'
282
288
  });
283
289
  }
284
290
 
@@ -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']],
@@ -153,15 +155,16 @@ function checkboxRenderer(hotInstance, TD, row, col, prop, value, cellProperties
153
155
  changeSelectedCheckboxesState();
154
156
  return !areSelectedCheckboxCells(); // False blocks next action associated with the keyboard shortcut.
155
157
  },
156
- runOnlyIf: () => hotInstance.getSettings().enterBeginsEditing
158
+ runOnlyIf: () => {
159
+ var _hotInstance$getSelec;
160
+ return hotInstance.getSettings().enterBeginsEditing && ((_hotInstance$getSelec = hotInstance.getSelectedRangeLast()) === null || _hotInstance$getSelec === void 0 ? void 0 : _hotInstance$getSelec.isSingle());
161
+ }
157
162
  }, {
158
163
  keys: [['delete'], ['backspace']],
159
164
  callback: () => {
160
165
  changeSelectedCheckboxesState(true);
161
166
  return !areSelectedCheckboxCells(); // False blocks next action associated with the keyboard shortcut.
162
- },
163
- relativeToGroup: _shortcutContexts.EDITOR_EDIT_GROUP,
164
- position: 'before'
167
+ }
165
168
  }], config);
166
169
  }
167
170
 
@@ -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']],
@@ -148,15 +150,16 @@ export function checkboxRenderer(hotInstance, TD, row, col, prop, value, cellPro
148
150
  changeSelectedCheckboxesState();
149
151
  return !areSelectedCheckboxCells(); // False blocks next action associated with the keyboard shortcut.
150
152
  },
151
- runOnlyIf: () => hotInstance.getSettings().enterBeginsEditing
153
+ runOnlyIf: () => {
154
+ var _hotInstance$getSelec;
155
+ return hotInstance.getSettings().enterBeginsEditing && ((_hotInstance$getSelec = hotInstance.getSelectedRangeLast()) === null || _hotInstance$getSelec === void 0 ? void 0 : _hotInstance$getSelec.isSingle());
156
+ }
152
157
  }, {
153
158
  keys: [['delete'], ['backspace']],
154
159
  callback: () => {
155
160
  changeSelectedCheckboxesState(true);
156
161
  return !areSelectedCheckboxCells(); // False blocks next action associated with the keyboard shortcut.
157
- },
158
- relativeToGroup: SHORTCUTS_GROUP_EDITOR,
159
- position: 'before'
162
+ }
160
163
  }], config);
161
164
  }
162
165
 
@@ -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");
@@ -28,6 +28,9 @@ function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.h
28
28
  * @class Selection
29
29
  * @util
30
30
  */
31
+ var _transformation = /*#__PURE__*/new WeakMap();
32
+ var _focusTransformation = /*#__PURE__*/new WeakMap();
33
+ var _isFocusSelectionChanged = /*#__PURE__*/new WeakMap();
31
34
  var _disableHeadersHighlight = /*#__PURE__*/new WeakMap();
32
35
  var _selectionSource = /*#__PURE__*/new WeakMap();
33
36
  var _expectedLayersCount = /*#__PURE__*/new WeakMap();
@@ -67,11 +70,17 @@ class Selection {
67
70
  */
68
71
  _defineProperty(this, "highlight", void 0);
69
72
  /**
70
- * The module for modifying coordinates.
73
+ * The module for modifying coordinates of the start and end selection.
71
74
  *
72
75
  * @type {Transformation}
73
76
  */
74
- _defineProperty(this, "transformation", void 0);
77
+ _classPrivateFieldInitSpec(this, _transformation, void 0);
78
+ /**
79
+ * The module for modifying coordinates of the focus selection.
80
+ *
81
+ * @type {Transformation}
82
+ */
83
+ _classPrivateFieldInitSpec(this, _focusTransformation, void 0);
75
84
  /**
76
85
  * The collection of the selection layer levels where the whole row was selected using the row header or
77
86
  * the corner header.
@@ -86,6 +95,12 @@ class Selection {
86
95
  * @type {Set<number>}
87
96
  */
88
97
  _defineProperty(this, "selectedByColumnHeader", new Set());
98
+ /**
99
+ * The flag which determines if the focus selection was changed.
100
+ *
101
+ * @type {boolean}
102
+ */
103
+ _classPrivateFieldInitSpec(this, _isFocusSelectionChanged, false);
89
104
  /**
90
105
  * When sets disable highlighting the headers even when the logical coordinates points on them.
91
106
  *
@@ -127,71 +142,112 @@ class Selection {
127
142
  createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),
128
143
  createCellRange: (highlight, from, to) => this.tableProps.createCellRange(highlight, from, to)
129
144
  });
130
- this.transformation = new _transformation.default(this.selectedRange, {
145
+ _classPrivateFieldSet(_transformation, this, new _transformation2.default(this.selectedRange, {
131
146
  rowIndexMapper: this.tableProps.rowIndexMapper,
132
147
  columnIndexMapper: this.tableProps.columnIndexMapper,
133
148
  countRenderableRows: () => this.tableProps.countRenderableRows(),
134
149
  countRenderableColumns: () => this.tableProps.countRenderableColumns(),
135
- countRowHeaders: () => this.tableProps.countRowHeaders(),
136
- countColHeaders: () => this.tableProps.countColHeaders(),
137
150
  visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),
138
151
  renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),
152
+ findFirstNonHiddenRenderableRow: function () {
153
+ return _this.tableProps.findFirstNonHiddenRenderableRow(...arguments);
154
+ },
155
+ findFirstNonHiddenRenderableColumn: function () {
156
+ return _this.tableProps.findFirstNonHiddenRenderableColumn(...arguments);
157
+ },
139
158
  createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),
140
- navigableHeaders: () => settings.navigableHeaders,
141
159
  fixedRowsBottom: () => settings.fixedRowsBottom,
142
160
  minSpareRows: () => settings.minSpareRows,
143
161
  minSpareCols: () => settings.minSpareCols,
144
162
  autoWrapRow: () => settings.autoWrapRow,
145
163
  autoWrapCol: () => settings.autoWrapCol
146
- });
147
- this.transformation.addLocalHook('beforeTransformStart', function () {
164
+ }));
165
+ _classPrivateFieldSet(_focusTransformation, this, new _transformation2.default(this.selectedRange, {
166
+ rowIndexMapper: this.tableProps.rowIndexMapper,
167
+ columnIndexMapper: this.tableProps.columnIndexMapper,
168
+ countRenderableRows: () => {
169
+ const range = this.selectedRange.current();
170
+ return this.tableProps.countRenderableRowsInRange(0, range.getOuterBottomEndCorner().row);
171
+ },
172
+ countRenderableColumns: () => {
173
+ const range = this.selectedRange.current();
174
+ return this.tableProps.countRenderableColumnsInRange(0, range.getOuterBottomEndCorner().col);
175
+ },
176
+ visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),
177
+ renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),
178
+ findFirstNonHiddenRenderableRow: function () {
179
+ return _this.tableProps.findFirstNonHiddenRenderableRow(...arguments);
180
+ },
181
+ findFirstNonHiddenRenderableColumn: function () {
182
+ return _this.tableProps.findFirstNonHiddenRenderableColumn(...arguments);
183
+ },
184
+ createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),
185
+ fixedRowsBottom: () => 0,
186
+ minSpareRows: () => 0,
187
+ minSpareCols: () => 0,
188
+ autoWrapRow: () => true,
189
+ autoWrapCol: () => true
190
+ }));
191
+ _classPrivateFieldGet(_transformation, this).addLocalHook('beforeTransformStart', function () {
148
192
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
149
193
  args[_key] = arguments[_key];
150
194
  }
151
195
  return _this.runLocalHooks('beforeModifyTransformStart', ...args);
152
196
  });
153
- this.transformation.addLocalHook('afterTransformStart', function () {
197
+ _classPrivateFieldGet(_transformation, this).addLocalHook('afterTransformStart', function () {
154
198
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
155
199
  args[_key2] = arguments[_key2];
156
200
  }
157
201
  return _this.runLocalHooks('afterModifyTransformStart', ...args);
158
202
  });
159
- this.transformation.addLocalHook('beforeTransformEnd', function () {
203
+ _classPrivateFieldGet(_transformation, this).addLocalHook('beforeTransformEnd', function () {
160
204
  for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
161
205
  args[_key3] = arguments[_key3];
162
206
  }
163
207
  return _this.runLocalHooks('beforeModifyTransformEnd', ...args);
164
208
  });
165
- this.transformation.addLocalHook('afterTransformEnd', function () {
209
+ _classPrivateFieldGet(_transformation, this).addLocalHook('afterTransformEnd', function () {
166
210
  for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
167
211
  args[_key4] = arguments[_key4];
168
212
  }
169
213
  return _this.runLocalHooks('afterModifyTransformEnd', ...args);
170
214
  });
171
- this.transformation.addLocalHook('insertRowRequire', function () {
215
+ _classPrivateFieldGet(_transformation, this).addLocalHook('insertRowRequire', function () {
172
216
  for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
173
217
  args[_key5] = arguments[_key5];
174
218
  }
175
219
  return _this.runLocalHooks('insertRowRequire', ...args);
176
220
  });
177
- this.transformation.addLocalHook('insertColRequire', function () {
221
+ _classPrivateFieldGet(_transformation, this).addLocalHook('insertColRequire', function () {
178
222
  for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
179
223
  args[_key6] = arguments[_key6];
180
224
  }
181
225
  return _this.runLocalHooks('insertColRequire', ...args);
182
226
  });
183
- this.transformation.addLocalHook('beforeRowWrap', function () {
227
+ _classPrivateFieldGet(_transformation, this).addLocalHook('beforeRowWrap', function () {
184
228
  for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
185
229
  args[_key7] = arguments[_key7];
186
230
  }
187
231
  return _this.runLocalHooks('beforeRowWrap', ...args);
188
232
  });
189
- this.transformation.addLocalHook('beforeColumnWrap', function () {
233
+ _classPrivateFieldGet(_transformation, this).addLocalHook('beforeColumnWrap', function () {
190
234
  for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
191
235
  args[_key8] = arguments[_key8];
192
236
  }
193
237
  return _this.runLocalHooks('beforeColumnWrap', ...args);
194
238
  });
239
+ _classPrivateFieldGet(_focusTransformation, this).addLocalHook('beforeTransformStart', function () {
240
+ for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
241
+ args[_key9] = arguments[_key9];
242
+ }
243
+ return _this.runLocalHooks('beforeModifyTransformFocus', ...args);
244
+ });
245
+ _classPrivateFieldGet(_focusTransformation, this).addLocalHook('afterTransformStart', function () {
246
+ for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
247
+ args[_key10] = arguments[_key10];
248
+ }
249
+ return _this.runLocalHooks('afterModifyTransformFocus', ...args);
250
+ });
195
251
  }
196
252
 
197
253
  /**
@@ -282,6 +338,7 @@ class Selection {
282
338
  // We are creating copy. We would like to modify just the start of the selection by below hook. Then original coords
283
339
  // should be handled by next methods.
284
340
  const coordsClone = coords.clone();
341
+ _classPrivateFieldSet(_isFocusSelectionChanged, this, false);
285
342
  this.runLocalHooks(`beforeSetRangeStart${fragment ? 'Only' : ''}`, coordsClone);
286
343
  if (!isMultipleMode || isMultipleMode && !isMultipleSelection && (0, _mixed.isUndefined)(multipleSelection)) {
287
344
  this.selectedRange.clear();
@@ -339,7 +396,20 @@ class Selection {
339
396
  cellRange.setFrom(cellRange.highlight);
340
397
  cellRange.setTo(cellRange.highlight);
341
398
  } else {
399
+ const horizontalDir = cellRange.getHorizontalDirection();
400
+ const verticalDir = cellRange.getVerticalDirection();
401
+ const isMultiple = this.isMultiple();
342
402
  cellRange.setTo(coordsClone);
403
+ if (isMultiple && (horizontalDir !== cellRange.getHorizontalDirection() || cellRange.getWidth() === 1 && !cellRange.includes(cellRange.highlight))) {
404
+ cellRange.from.assign({
405
+ col: cellRange.highlight.col
406
+ });
407
+ }
408
+ if (isMultiple && (verticalDir !== cellRange.getVerticalDirection() || cellRange.getHeight() === 1 && !cellRange.includes(cellRange.highlight))) {
409
+ cellRange.from.assign({
410
+ row: cellRange.highlight.row
411
+ });
412
+ }
343
413
  }
344
414
 
345
415
  // Prevent creating "area" selection that overlaps headers.
@@ -349,11 +419,7 @@ class Selection {
349
419
  }
350
420
  }
351
421
  this.runLocalHooks('beforeHighlightSet');
352
- const focusHighlight = this.highlight.getFocus();
353
- focusHighlight.clear();
354
- if (this.highlight.isEnabledFor(_highlight.FOCUS_TYPE, cellRange.highlight)) {
355
- focusHighlight.add(this.selectedRange.current().highlight).commit().syncWith(cellRange);
356
- }
422
+ this.setRangeFocus(this.selectedRange.current().highlight);
357
423
  const layerLevel = this.getLayerLevel();
358
424
 
359
425
  // If the next layer level is lower than previous then clear all area and header highlights. This is the
@@ -441,15 +507,31 @@ class Selection {
441
507
  }
442
508
 
443
509
  /**
444
- * Returns information if we have a multiselection. This method check multiselection only on the latest layer of
445
- * the selection.
510
+ * Sets the selection focus position at the specified coordinates.
446
511
  *
447
- * @returns {boolean}
512
+ * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.
448
513
  */
449
- isMultiple() {
450
- const isMultipleListener = (0, _object.createObjectPropListener)(!this.selectedRange.current().isSingle());
451
- this.runLocalHooks('afterIsMultipleSelection', isMultipleListener);
452
- return isMultipleListener.value;
514
+ setRangeFocus(coords) {
515
+ if (this.selectedRange.isEmpty()) {
516
+ return;
517
+ }
518
+ const cellRange = this.selectedRange.current();
519
+ if (!this.inProgress) {
520
+ this.runLocalHooks('beforeSetFocus', coords);
521
+ }
522
+ const focusHighlight = this.highlight.getFocus();
523
+ focusHighlight.clear();
524
+ cellRange.setHighlight(coords);
525
+ if (!this.inProgress) {
526
+ this.runLocalHooks('beforeHighlightSet');
527
+ }
528
+ if (this.highlight.isEnabledFor(_highlight.FOCUS_TYPE, cellRange.highlight)) {
529
+ focusHighlight.add(cellRange.highlight).commit().syncWith(cellRange);
530
+ }
531
+ if (!this.inProgress) {
532
+ _classPrivateFieldSet(_isFocusSelectionChanged, this, true);
533
+ this.runLocalHooks('afterSetFocus', cellRange.highlight);
534
+ }
453
535
  }
454
536
 
455
537
  /**
@@ -462,7 +544,13 @@ class Selection {
462
544
  */
463
545
  transformStart(rowDelta, colDelta) {
464
546
  let createMissingRecords = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
465
- this.setRangeStart(this.transformation.transformStart(rowDelta, colDelta, createMissingRecords));
547
+ if (this.settings.navigableHeaders) {
548
+ _classPrivateFieldGet(_transformation, this).setOffsetSize({
549
+ x: this.tableProps.countRowHeaders(),
550
+ y: this.tableProps.countColHeaders()
551
+ });
552
+ }
553
+ this.setRangeStart(_classPrivateFieldGet(_transformation, this).transformStart(rowDelta, colDelta, createMissingRecords));
466
554
  }
467
555
 
468
556
  /**
@@ -472,7 +560,44 @@ class Selection {
472
560
  * @param {number} colDelta Columns number to move, value can be passed as negative number.
473
561
  */
474
562
  transformEnd(rowDelta, colDelta) {
475
- this.setRangeEnd(this.transformation.transformEnd(rowDelta, colDelta));
563
+ if (this.settings.navigableHeaders) {
564
+ _classPrivateFieldGet(_transformation, this).setOffsetSize({
565
+ x: this.tableProps.countRowHeaders(),
566
+ y: this.tableProps.countColHeaders()
567
+ });
568
+ }
569
+ this.setRangeEnd(_classPrivateFieldGet(_transformation, this).transformEnd(rowDelta, colDelta));
570
+ }
571
+
572
+ /**
573
+ * Transforms the focus cell selection relative to the current focus position.
574
+ *
575
+ * @param {number} rowDelta Rows number to move, value can be passed as negative number.
576
+ * @param {number} colDelta Columns number to move, value can be passed as negative number.
577
+ */
578
+ transformFocus(rowDelta, colDelta) {
579
+ const range = this.selectedRange.current();
580
+ const {
581
+ row,
582
+ col
583
+ } = range.getOuterTopStartCorner();
584
+ const columnsInRange = this.tableProps.countRenderableColumnsInRange(0, col - 1);
585
+ const rowsInRange = this.tableProps.countRenderableRowsInRange(0, row - 1);
586
+ if (range.highlight.isHeader()) {
587
+ // for header focus selection calculate the new coords based on the selection including headers
588
+ _classPrivateFieldGet(_focusTransformation, this).setOffsetSize({
589
+ x: col < 0 ? Math.abs(col) : -columnsInRange,
590
+ y: row < 0 ? Math.abs(row) : -rowsInRange
591
+ });
592
+ } else {
593
+ // for focus selection in cells calculate the new coords only based on the selected cells
594
+ _classPrivateFieldGet(_focusTransformation, this).setOffsetSize({
595
+ x: col < 0 ? 0 : -columnsInRange,
596
+ y: row < 0 ? 0 : -rowsInRange
597
+ });
598
+ }
599
+ const focusCoords = _classPrivateFieldGet(_focusTransformation, this).transformStart(rowDelta, colDelta);
600
+ this.setRangeFocus(focusCoords.normalize());
476
601
  }
477
602
 
478
603
  /**
@@ -493,6 +618,30 @@ class Selection {
493
618
  return !this.selectedRange.isEmpty();
494
619
  }
495
620
 
621
+ /**
622
+ * Returns information if we have a multi-selection. This method check multi-selection only on the latest layer of
623
+ * the selection.
624
+ *
625
+ * @returns {boolean}
626
+ */
627
+ isMultiple() {
628
+ if (!this.isSelected()) {
629
+ return false;
630
+ }
631
+ const isMultipleListener = (0, _object.createObjectPropListener)(!this.selectedRange.current().isSingle());
632
+ this.runLocalHooks('afterIsMultipleSelection', isMultipleListener);
633
+ return isMultipleListener.value;
634
+ }
635
+
636
+ /**
637
+ * Checks if the last selection involves changing the focus cell position only.
638
+ *
639
+ * @returns {boolean}
640
+ */
641
+ isFocusSelectionChanged() {
642
+ return this.isSelected() && _classPrivateFieldGet(_isFocusSelectionChanged, this);
643
+ }
644
+
496
645
  /**
497
646
  * Returns `true` if the selection was applied by clicking to the row header. If the `layerLevel`
498
647
  * argument is passed then only that layer will be checked. Otherwise, it checks if any row header
@@ -775,9 +924,10 @@ class Selection {
775
924
  *
776
925
  * @param {number|string} startColumn Visual column index or column property from which the selection starts.
777
926
  * @param {number|string} [endColumn] Visual column index or column property from to the selection finishes.
778
- * @param {number} [focusPosition=0] The argument allows changing the cell/header focus position.
779
- * The value can take visual row index from -N to N, where negative values
780
- * point to the headers and positive values point to the cell range.
927
+ * @param {number | { row: number, col: number }} [focusPosition=0] The argument allows changing the cell/header focus
928
+ * position. The value can take visual row index from -N to N, where negative values point to the headers and positive
929
+ * values point to the cell range. An object with `row` and `col` properties also can be passed to change the focus
930
+ * position horizontally.
781
931
  * @returns {boolean} Returns `true` if selection was successful, `false` otherwise.
782
932
  */
783
933
  selectColumns(startColumn) {
@@ -798,11 +948,20 @@ class Selection {
798
948
  countColHeaders
799
949
  });
800
950
  if (isValid) {
801
- const fromRow = countColHeaders === 0 ? 0 : (0, _number.clamp)(focusPosition, columnHeaderLastIndex, -1);
951
+ let highlightRow = 0;
952
+ let highlightColumn = 0;
953
+ if (Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {
954
+ highlightRow = (0, _number.clamp)(focusPosition.row, columnHeaderLastIndex, countRows - 1);
955
+ highlightColumn = (0, _number.clamp)(focusPosition.col, Math.min(start, end), Math.max(start, end));
956
+ } else {
957
+ highlightRow = (0, _number.clamp)(focusPosition, columnHeaderLastIndex, countRows - 1);
958
+ highlightColumn = start;
959
+ }
960
+ const highlight = this.tableProps.createCellCoords(highlightRow, highlightColumn);
961
+ const fromRow = countColHeaders === 0 ? 0 : (0, _number.clamp)(highlight.row, columnHeaderLastIndex, -1);
802
962
  const toRow = countRows - 1;
803
963
  const from = this.tableProps.createCellCoords(fromRow, start);
804
964
  const to = this.tableProps.createCellCoords(toRow, end);
805
- const highlight = this.tableProps.createCellCoords((0, _number.clamp)(focusPosition, columnHeaderLastIndex, countRows - 1), start);
806
965
  this.runLocalHooks('beforeSelectColumns', from, to, highlight);
807
966
 
808
967
  // disallow modifying row axis for that hooks
@@ -822,9 +981,10 @@ class Selection {
822
981
  *
823
982
  * @param {number} startRow Visual row index from which the selection starts.
824
983
  * @param {number} [endRow] Visual row index from to the selection finishes.
825
- * @param {number} [focusPosition=0] The argument allows changing the cell/header focus position.
826
- * The value can take visual column index from -N to N, where negative values
827
- * point to the headers and positive values point to the cell range.
984
+ * @param {number | { row: number, col: number }} [focusPosition=0] The argument allows changing the cell/header focus
985
+ * position. The value can take visual row index from -N to N, where negative values point to the headers and positive
986
+ * values point to the cell range. An object with `row` and `col` properties also can be passed to change the focus
987
+ * position horizontally.
828
988
  * @returns {boolean} Returns `true` if selection was successful, `false` otherwise.
829
989
  */
830
990
  selectRows(startRow) {
@@ -843,11 +1003,20 @@ class Selection {
843
1003
  countColHeaders: 0
844
1004
  });
845
1005
  if (isValid) {
846
- const fromColumn = countRowHeaders === 0 ? 0 : (0, _number.clamp)(focusPosition, rowHeaderLastIndex, -1);
1006
+ let highlightRow = 0;
1007
+ let highlightColumn = 0;
1008
+ if (Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {
1009
+ highlightRow = (0, _number.clamp)(focusPosition.row, Math.min(startRow, endRow), Math.max(startRow, endRow));
1010
+ highlightColumn = (0, _number.clamp)(focusPosition.col, rowHeaderLastIndex, countCols - 1);
1011
+ } else {
1012
+ highlightRow = startRow;
1013
+ highlightColumn = (0, _number.clamp)(focusPosition, rowHeaderLastIndex, countCols - 1);
1014
+ }
1015
+ const highlight = this.tableProps.createCellCoords(highlightRow, highlightColumn);
1016
+ const fromColumn = countRowHeaders === 0 ? 0 : (0, _number.clamp)(highlight.col, rowHeaderLastIndex, -1);
847
1017
  const toColumn = countCols - 1;
848
1018
  const from = this.tableProps.createCellCoords(startRow, fromColumn);
849
1019
  const to = this.tableProps.createCellCoords(endRow, toColumn);
850
- const highlight = this.tableProps.createCellCoords(startRow, (0, _number.clamp)(focusPosition, rowHeaderLastIndex, countCols - 1));
851
1020
  this.runLocalHooks('beforeSelectRows', from, to, highlight);
852
1021
 
853
1022
  // disallow modifying column axis for that hooks