handsontable 14.1.0-next-1211447-20240205 → 14.2.0-next-4873a35-20240228

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.
Files changed (163) hide show
  1. package/3rdparty/walkontable/src/core/_base.js +12 -0
  2. package/3rdparty/walkontable/src/core/_base.mjs +12 -0
  3. package/3rdparty/walkontable/src/scroll.js +131 -98
  4. package/3rdparty/walkontable/src/scroll.mjs +133 -100
  5. package/3rdparty/walkontable/src/selection/border/border.js +3 -3
  6. package/3rdparty/walkontable/src/selection/border/border.mjs +3 -3
  7. package/3rdparty/walkontable/src/table/mixin/calculatedColumns.js +26 -0
  8. package/3rdparty/walkontable/src/table/mixin/calculatedColumns.mjs +26 -0
  9. package/3rdparty/walkontable/src/table/mixin/calculatedRows.js +26 -0
  10. package/3rdparty/walkontable/src/table/mixin/calculatedRows.mjs +26 -0
  11. package/3rdparty/walkontable/src/table/mixin/stickyColumnsStart.js +20 -0
  12. package/3rdparty/walkontable/src/table/mixin/stickyColumnsStart.mjs +20 -0
  13. package/3rdparty/walkontable/src/table/mixin/stickyRowsBottom.js +20 -0
  14. package/3rdparty/walkontable/src/table/mixin/stickyRowsBottom.mjs +20 -0
  15. package/3rdparty/walkontable/src/table/mixin/stickyRowsTop.js +20 -0
  16. package/3rdparty/walkontable/src/table/mixin/stickyRowsTop.mjs +20 -0
  17. package/3rdparty/walkontable/src/table.js +2 -0
  18. package/3rdparty/walkontable/src/table.mjs +2 -0
  19. package/3rdparty/walkontable/src/viewport.js +9 -0
  20. package/3rdparty/walkontable/src/viewport.mjs +10 -1
  21. package/CHANGELOG.md +38 -0
  22. package/base.js +2 -2
  23. package/base.mjs +2 -2
  24. package/core/index.js +6 -0
  25. package/core/index.mjs +2 -1
  26. package/core/viewportScroll/index.js +65 -0
  27. package/core/viewportScroll/index.mjs +61 -0
  28. package/core/viewportScroll/scrollStrategies/columnHeaderScroll.js +20 -0
  29. package/core/viewportScroll/scrollStrategies/columnHeaderScroll.mjs +16 -0
  30. package/core/viewportScroll/scrollStrategies/cornerHeaderScroll.js +14 -0
  31. package/core/viewportScroll/scrollStrategies/cornerHeaderScroll.mjs +10 -0
  32. package/core/viewportScroll/scrollStrategies/multipleScroll.js +15 -0
  33. package/core/viewportScroll/scrollStrategies/multipleScroll.mjs +11 -0
  34. package/core/viewportScroll/scrollStrategies/noncontiguousScroll.js +15 -0
  35. package/core/viewportScroll/scrollStrategies/noncontiguousScroll.mjs +11 -0
  36. package/core/viewportScroll/scrollStrategies/rowHeaderScroll.js +20 -0
  37. package/core/viewportScroll/scrollStrategies/rowHeaderScroll.mjs +16 -0
  38. package/core/viewportScroll/scrollStrategies/singleScroll.js +46 -0
  39. package/core/viewportScroll/scrollStrategies/singleScroll.mjs +42 -0
  40. package/core.d.ts +1 -1
  41. package/core.js +11 -52
  42. package/core.mjs +12 -53
  43. package/dataMap/metaManager/index.js +1 -1
  44. package/dataMap/metaManager/index.mjs +1 -1
  45. package/dataMap/metaManager/metaLayers/cellMeta.js +6 -1
  46. package/dataMap/metaManager/metaLayers/cellMeta.mjs +6 -1
  47. package/dataMap/metaManager/metaSchema.js +36 -12
  48. package/dataMap/metaManager/metaSchema.mjs +36 -12
  49. package/dist/handsontable.css +2 -2
  50. package/dist/handsontable.full.css +2 -2
  51. package/dist/handsontable.full.js +2997 -1929
  52. package/dist/handsontable.full.min.css +2 -2
  53. package/dist/handsontable.full.min.js +42 -42
  54. package/dist/handsontable.js +2999 -1931
  55. package/dist/handsontable.min.css +2 -2
  56. package/dist/handsontable.min.js +25 -25
  57. package/dist/languages/all.js +130 -25
  58. package/dist/languages/all.min.js +1 -1
  59. package/dist/languages/hr-HR.js +167 -0
  60. package/dist/languages/hr-HR.min.js +1 -0
  61. package/editorManager.js +15 -4
  62. package/editorManager.mjs +15 -4
  63. package/editors/autocompleteEditor/autocompleteEditor.js +2 -2
  64. package/editors/autocompleteEditor/autocompleteEditor.mjs +2 -2
  65. package/editors/baseEditor/baseEditor.js +1 -1
  66. package/editors/baseEditor/baseEditor.mjs +1 -1
  67. package/editors/checkboxEditor/checkboxEditor.js +5 -4
  68. package/editors/checkboxEditor/checkboxEditor.mjs +5 -4
  69. package/editors/dateEditor/dateEditor.js +1 -1
  70. package/editors/dateEditor/dateEditor.mjs +1 -1
  71. package/editors/dropdownEditor/dropdownEditor.js +1 -1
  72. package/editors/dropdownEditor/dropdownEditor.mjs +1 -1
  73. package/editors/handsontableEditor/handsontableEditor.js +1 -1
  74. package/editors/handsontableEditor/handsontableEditor.mjs +1 -1
  75. package/editors/selectEditor/selectEditor.js +1 -1
  76. package/editors/selectEditor/selectEditor.mjs +1 -1
  77. package/editors/textEditor/textEditor.js +1 -2
  78. package/editors/textEditor/textEditor.mjs +1 -2
  79. package/editors/timeEditor/timeEditor.js +1 -1
  80. package/editors/timeEditor/timeEditor.mjs +1 -1
  81. package/helpers/mixed.js +2 -2
  82. package/helpers/mixed.mjs +2 -2
  83. package/helpers/moves.js +86 -0
  84. package/helpers/moves.mjs +82 -0
  85. package/i18n/languages/hr-HR.js +96 -0
  86. package/i18n/languages/hr-HR.mjs +90 -0
  87. package/i18n/languages/index.js +2 -0
  88. package/i18n/languages/index.mjs +2 -1
  89. package/languages/all.js +130 -25
  90. package/languages/hr-HR.js +167 -0
  91. package/languages/hr-HR.mjs +92 -0
  92. package/languages/index.js +130 -25
  93. package/languages/index.mjs +2 -1
  94. package/package.json +11 -1
  95. package/pluginHooks.d.ts +4 -2
  96. package/pluginHooks.js +33 -3
  97. package/pluginHooks.mjs +33 -3
  98. package/plugins/autoColumnSize/autoColumnSize.js +6 -1
  99. package/plugins/autoColumnSize/autoColumnSize.mjs +6 -1
  100. package/plugins/autoRowSize/autoRowSize.js +5 -0
  101. package/plugins/autoRowSize/autoRowSize.mjs +5 -0
  102. package/plugins/autofill/autofill.js +3 -2
  103. package/plugins/autofill/autofill.mjs +3 -2
  104. package/plugins/columnSummary/columnSummary.js +1 -1
  105. package/plugins/columnSummary/columnSummary.mjs +1 -1
  106. package/plugins/dropdownMenu/dropdownMenu.js +58 -4
  107. package/plugins/dropdownMenu/dropdownMenu.mjs +58 -4
  108. package/plugins/filters/component/value.js +51 -5
  109. package/plugins/filters/component/value.mjs +51 -5
  110. package/plugins/filters/utils.js +1 -1
  111. package/plugins/filters/utils.mjs +1 -1
  112. package/plugins/formulas/formulas.js +10 -1
  113. package/plugins/formulas/formulas.mjs +10 -1
  114. package/plugins/formulas/indexSyncer/axisSyncer.js +3 -75
  115. package/plugins/formulas/indexSyncer/axisSyncer.mjs +3 -75
  116. package/plugins/manualColumnResize/manualColumnResize.js +3 -0
  117. package/plugins/manualColumnResize/manualColumnResize.mjs +3 -0
  118. package/plugins/mergeCells/cellsCollection.js +1 -1
  119. package/plugins/mergeCells/cellsCollection.mjs +1 -1
  120. package/plugins/mergeCells/mergeCells.js +30 -0
  121. package/plugins/mergeCells/mergeCells.mjs +30 -0
  122. package/plugins/undoRedo/undoRedo.js +61 -14
  123. package/plugins/undoRedo/undoRedo.mjs +61 -14
  124. package/renderers/autocompleteRenderer/autocompleteRenderer.js +1 -1
  125. package/renderers/autocompleteRenderer/autocompleteRenderer.mjs +1 -1
  126. package/renderers/baseRenderer/baseRenderer.js +1 -1
  127. package/renderers/baseRenderer/baseRenderer.mjs +1 -1
  128. package/renderers/checkboxRenderer/checkboxRenderer.js +36 -8
  129. package/renderers/checkboxRenderer/checkboxRenderer.mjs +36 -8
  130. package/renderers/dateRenderer/dateRenderer.js +1 -1
  131. package/renderers/dateRenderer/dateRenderer.mjs +1 -1
  132. package/renderers/dropdownRenderer/dropdownRenderer.js +1 -1
  133. package/renderers/dropdownRenderer/dropdownRenderer.mjs +1 -1
  134. package/renderers/handsontableRenderer/handsontableRenderer.js +1 -1
  135. package/renderers/handsontableRenderer/handsontableRenderer.mjs +1 -1
  136. package/renderers/htmlRenderer/htmlRenderer.js +1 -1
  137. package/renderers/htmlRenderer/htmlRenderer.mjs +1 -1
  138. package/renderers/numericRenderer/index.js +2 -1
  139. package/renderers/numericRenderer/index.mjs +1 -1
  140. package/renderers/numericRenderer/numericRenderer.js +28 -13
  141. package/renderers/numericRenderer/numericRenderer.mjs +27 -13
  142. package/renderers/passwordRenderer/passwordRenderer.js +1 -1
  143. package/renderers/passwordRenderer/passwordRenderer.mjs +1 -1
  144. package/renderers/selectRenderer/selectRenderer.js +1 -1
  145. package/renderers/selectRenderer/selectRenderer.mjs +1 -1
  146. package/renderers/textRenderer/textRenderer.js +1 -1
  147. package/renderers/textRenderer/textRenderer.mjs +1 -1
  148. package/renderers/timeRenderer/timeRenderer.js +1 -1
  149. package/renderers/timeRenderer/timeRenderer.mjs +1 -1
  150. package/selection/mouseEventHandler.js +4 -0
  151. package/selection/mouseEventHandler.mjs +4 -0
  152. package/selection/selection.js +64 -5
  153. package/selection/selection.mjs +64 -5
  154. package/shortcuts/recorder.js +27 -8
  155. package/shortcuts/recorder.mjs +27 -8
  156. package/tableView.js +86 -5
  157. package/tableView.mjs +87 -6
  158. package/utils/autoResize.js +0 -1
  159. package/utils/autoResize.mjs +0 -1
  160. package/utils/ghostTable.js +6 -6
  161. package/utils/ghostTable.mjs +6 -6
  162. package/utils/parseTable.js +9 -1
  163. package/utils/parseTable.mjs +9 -1
@@ -21,16 +21,18 @@ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollect
21
21
  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; }
22
22
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
23
23
  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); }
24
- function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
25
- function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
26
24
  function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
27
- function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
28
25
  function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
26
+ function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
27
+ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
28
+ function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
29
29
  /**
30
30
  * @class Selection
31
31
  * @util
32
32
  */
33
33
  var _disableHeadersHighlight = /*#__PURE__*/new WeakMap();
34
+ var _selectionSource = /*#__PURE__*/new WeakMap();
35
+ var _expectedLayersCount = /*#__PURE__*/new WeakMap();
34
36
  class Selection {
35
37
  constructor(settings, tableProps) {
36
38
  var _this = this;
@@ -95,6 +97,25 @@ class Selection {
95
97
  writable: true,
96
98
  value: false
97
99
  });
100
+ /**
101
+ * The source of the selection. It can be one of the following values: `mouse`, `unknown` or any other string.
102
+ *
103
+ * @type {'mouse' | 'unknown' | string}
104
+ */
105
+ _classPrivateFieldInitSpec(this, _selectionSource, {
106
+ writable: true,
107
+ value: 'unknown'
108
+ });
109
+ /**
110
+ * The number of expected layers. It is used mostly to track when the last selection layer of non-contiguous
111
+ * selection is applied, thus the viewport scroll is triggered.
112
+ *
113
+ * @param {number}
114
+ */
115
+ _classPrivateFieldInitSpec(this, _expectedLayersCount, {
116
+ writable: true,
117
+ value: -1
118
+ });
98
119
  this.settings = settings;
99
120
  this.tableProps = tableProps;
100
121
  this.highlight = new _highlight.default({
@@ -193,6 +214,41 @@ class Selection {
193
214
  return this.selectedRange;
194
215
  }
195
216
 
217
+ /**
218
+ * Marks the source of the selection. It can be one of the following values: `mouse`, or any other string.
219
+ *
220
+ * @param {'mouse' | 'unknown' | string} sourceName The source name.
221
+ */
222
+ markSource(sourceName) {
223
+ _classPrivateFieldSet(this, _selectionSource, sourceName);
224
+ }
225
+
226
+ /**
227
+ * Marks end of the selection source. It restores the selection source to default value which is 'unknown'.
228
+ */
229
+ markEndSource() {
230
+ _classPrivateFieldSet(this, _selectionSource, 'unknown');
231
+ }
232
+
233
+ /**
234
+ * Returns the source of the selection.
235
+ *
236
+ * @returns {'mouse' | 'unknown' | string}
237
+ */
238
+ getSelectionSource() {
239
+ return _classPrivateFieldGet(this, _selectionSource);
240
+ }
241
+
242
+ /**
243
+ * Set the number of expected layers. The method is not obligatory to call. It is used mostly internally
244
+ * to determine when the last selection layer of non-contiguous is applied, thus the viewport scroll is triggered.
245
+ *
246
+ * @param {number} layersCount The number of expected layers.
247
+ */
248
+ setExpectedLayers(layersCount) {
249
+ _classPrivateFieldSet(this, _expectedLayersCount, layersCount);
250
+ }
251
+
196
252
  /**
197
253
  * Indicate that selection process began. It sets internally `.inProgress` property to `true`.
198
254
  */
@@ -206,6 +262,7 @@ class Selection {
206
262
  finish() {
207
263
  this.runLocalHooks('afterSelectionFinished', Array.from(this.selectedRange));
208
264
  this.inProgress = false;
265
+ _classPrivateFieldSet(this, _expectedLayersCount, -1);
209
266
  }
210
267
 
211
268
  /**
@@ -390,7 +447,8 @@ class Selection {
390
447
  activeCornerHeaderHighlight.add(this.tableProps.createCellCoords(-this.tableProps.countColHeaders(), -this.tableProps.countRowHeaders())).add(this.tableProps.createCellCoords(-1, -1)).commit();
391
448
  }
392
449
  }
393
- this.runLocalHooks('afterSetRangeEnd', coords);
450
+ const isLastLayer = _classPrivateFieldGet(this, _expectedLayersCount) === -1 || this.selectedRange.size() === _classPrivateFieldGet(this, _expectedLayersCount);
451
+ this.runLocalHooks('afterSetRangeEnd', coords, isLastLayer);
394
452
  }
395
453
 
396
454
  /**
@@ -708,6 +766,7 @@ class Selection {
708
766
  });
709
767
  if (isValid) {
710
768
  this.clear();
769
+ this.setExpectedLayers(selectionRanges.length);
711
770
  (0, _array.arrayEach)(selectionRanges, selection => {
712
771
  const {
713
772
  from,
@@ -715,8 +774,8 @@ class Selection {
715
774
  } = selectionSchemaNormalizer(selection);
716
775
  this.setRangeStartOnly(from.clone(), false);
717
776
  this.setRangeEnd(to.clone());
718
- this.finish();
719
777
  });
778
+ this.finish();
720
779
  }
721
780
  return isValid;
722
781
  }
@@ -4,11 +4,11 @@ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollect
4
4
  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; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
6
6
  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); }
7
- function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
8
- function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
9
7
  function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
10
- function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
11
8
  function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
9
+ function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
10
+ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
11
+ function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
12
12
  import Highlight, { AREA_TYPE, HEADER_TYPE, FOCUS_TYPE } from "./highlight/highlight.mjs";
13
13
  import SelectionRange from "./range.mjs";
14
14
  import { createObjectPropListener, mixin } from "./../helpers/object.mjs";
@@ -25,6 +25,8 @@ import { A11Y_SELECTED } from "../helpers/a11y.mjs";
25
25
  * @util
26
26
  */
27
27
  var _disableHeadersHighlight = /*#__PURE__*/new WeakMap();
28
+ var _selectionSource = /*#__PURE__*/new WeakMap();
29
+ var _expectedLayersCount = /*#__PURE__*/new WeakMap();
28
30
  class Selection {
29
31
  constructor(settings, tableProps) {
30
32
  var _this = this;
@@ -89,6 +91,25 @@ class Selection {
89
91
  writable: true,
90
92
  value: false
91
93
  });
94
+ /**
95
+ * The source of the selection. It can be one of the following values: `mouse`, `unknown` or any other string.
96
+ *
97
+ * @type {'mouse' | 'unknown' | string}
98
+ */
99
+ _classPrivateFieldInitSpec(this, _selectionSource, {
100
+ writable: true,
101
+ value: 'unknown'
102
+ });
103
+ /**
104
+ * The number of expected layers. It is used mostly to track when the last selection layer of non-contiguous
105
+ * selection is applied, thus the viewport scroll is triggered.
106
+ *
107
+ * @param {number}
108
+ */
109
+ _classPrivateFieldInitSpec(this, _expectedLayersCount, {
110
+ writable: true,
111
+ value: -1
112
+ });
92
113
  this.settings = settings;
93
114
  this.tableProps = tableProps;
94
115
  this.highlight = new Highlight({
@@ -187,6 +208,41 @@ class Selection {
187
208
  return this.selectedRange;
188
209
  }
189
210
 
211
+ /**
212
+ * Marks the source of the selection. It can be one of the following values: `mouse`, or any other string.
213
+ *
214
+ * @param {'mouse' | 'unknown' | string} sourceName The source name.
215
+ */
216
+ markSource(sourceName) {
217
+ _classPrivateFieldSet(this, _selectionSource, sourceName);
218
+ }
219
+
220
+ /**
221
+ * Marks end of the selection source. It restores the selection source to default value which is 'unknown'.
222
+ */
223
+ markEndSource() {
224
+ _classPrivateFieldSet(this, _selectionSource, 'unknown');
225
+ }
226
+
227
+ /**
228
+ * Returns the source of the selection.
229
+ *
230
+ * @returns {'mouse' | 'unknown' | string}
231
+ */
232
+ getSelectionSource() {
233
+ return _classPrivateFieldGet(this, _selectionSource);
234
+ }
235
+
236
+ /**
237
+ * Set the number of expected layers. The method is not obligatory to call. It is used mostly internally
238
+ * to determine when the last selection layer of non-contiguous is applied, thus the viewport scroll is triggered.
239
+ *
240
+ * @param {number} layersCount The number of expected layers.
241
+ */
242
+ setExpectedLayers(layersCount) {
243
+ _classPrivateFieldSet(this, _expectedLayersCount, layersCount);
244
+ }
245
+
190
246
  /**
191
247
  * Indicate that selection process began. It sets internally `.inProgress` property to `true`.
192
248
  */
@@ -200,6 +256,7 @@ class Selection {
200
256
  finish() {
201
257
  this.runLocalHooks('afterSelectionFinished', Array.from(this.selectedRange));
202
258
  this.inProgress = false;
259
+ _classPrivateFieldSet(this, _expectedLayersCount, -1);
203
260
  }
204
261
 
205
262
  /**
@@ -384,7 +441,8 @@ class Selection {
384
441
  activeCornerHeaderHighlight.add(this.tableProps.createCellCoords(-this.tableProps.countColHeaders(), -this.tableProps.countRowHeaders())).add(this.tableProps.createCellCoords(-1, -1)).commit();
385
442
  }
386
443
  }
387
- this.runLocalHooks('afterSetRangeEnd', coords);
444
+ const isLastLayer = _classPrivateFieldGet(this, _expectedLayersCount) === -1 || this.selectedRange.size() === _classPrivateFieldGet(this, _expectedLayersCount);
445
+ this.runLocalHooks('afterSetRangeEnd', coords, isLastLayer);
388
446
  }
389
447
 
390
448
  /**
@@ -702,6 +760,7 @@ class Selection {
702
760
  });
703
761
  if (isValid) {
704
762
  this.clear();
763
+ this.setExpectedLayers(selectionRanges.length);
705
764
  arrayEach(selectionRanges, selection => {
706
765
  const {
707
766
  from,
@@ -709,8 +768,8 @@ class Selection {
709
768
  } = selectionSchemaNormalizer(selection);
710
769
  this.setRangeStartOnly(from.clone(), false);
711
770
  this.setRangeEnd(to.clone());
712
- this.finish();
713
771
  });
772
+ this.finish();
714
773
  }
715
774
  return isValid;
716
775
  }
@@ -10,6 +10,7 @@ var _element = require("../helpers/dom/element");
10
10
  var _browser = require("../helpers/browser");
11
11
  const MODIFIER_KEYS = ['meta', 'alt', 'shift', 'control'];
12
12
  const modifierKeysObserver = (0, _keyObserver.createKeysObserver)();
13
+ const modKeyListeners = [];
13
14
  let instanceCounter = 0;
14
15
 
15
16
  /* eslint-disable jsdoc/require-description-complete-sentence */
@@ -108,9 +109,11 @@ function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDown, call
108
109
  * @param {KeyboardEvent} event The event object
109
110
  */
110
111
  const onkeydownForModKeys = event => {
111
- const pressedKey = (0, _utils.normalizeEventKey)(event);
112
- if (isModifierKey(pressedKey)) {
113
- modifierKeysObserver.press(pressedKey);
112
+ if (event.key) {
113
+ const pressedKey = (0, _utils.normalizeEventKey)(event);
114
+ if (isModifierKey(pressedKey)) {
115
+ modifierKeysObserver.press(pressedKey);
116
+ }
114
117
  }
115
118
  };
116
119
 
@@ -121,9 +124,11 @@ function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDown, call
121
124
  * @param {KeyboardEvent} event The event object
122
125
  */
123
126
  const onkeyupForModKeys = event => {
124
- const pressedKey = (0, _utils.normalizeEventKey)(event);
125
- if (isModifierKey(pressedKey)) {
126
- modifierKeysObserver.release(pressedKey);
127
+ if (event.key) {
128
+ const pressedKey = (0, _utils.normalizeEventKey)(event);
129
+ if (isModifierKey(pressedKey)) {
130
+ modifierKeysObserver.release(pressedKey);
131
+ }
127
132
  }
128
133
  };
129
134
 
@@ -145,7 +150,15 @@ function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDown, call
145
150
  while (eventTarget) {
146
151
  if (instanceCounter === 1) {
147
152
  eventTarget.document.documentElement.addEventListener('keydown', onkeydownForModKeys);
153
+ modKeyListeners.push({
154
+ event: 'keydown',
155
+ listener: onkeydownForModKeys
156
+ });
148
157
  eventTarget.document.documentElement.addEventListener('keyup', onkeyupForModKeys);
158
+ modKeyListeners.push({
159
+ event: 'keyup',
160
+ listener: onkeyupForModKeys
161
+ });
149
162
  }
150
163
  eventTarget.document.documentElement.addEventListener('keydown', onkeydown);
151
164
  eventTarget.document.documentElement.addEventListener('blur', onblur);
@@ -161,8 +174,14 @@ function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDown, call
161
174
  instanceCounter -= 1;
162
175
  while (eventTarget) {
163
176
  if (instanceCounter === 0) {
164
- eventTarget.document.documentElement.removeEventListener('keydown', onkeydownForModKeys);
165
- eventTarget.document.documentElement.removeEventListener('keyup', onkeyupForModKeys);
177
+ for (let i = 0; i < modKeyListeners.length; i++) {
178
+ const {
179
+ event,
180
+ listener
181
+ } = modKeyListeners[i];
182
+ eventTarget.document.documentElement.removeEventListener(event, listener);
183
+ }
184
+ modKeyListeners.length = 0;
166
185
  }
167
186
  eventTarget.document.documentElement.removeEventListener('keydown', onkeydown);
168
187
  eventTarget.document.documentElement.removeEventListener('blur', onblur);
@@ -6,6 +6,7 @@ import { getParentWindow } from "../helpers/dom/element.mjs";
6
6
  import { isMacOS } from "../helpers/browser.mjs";
7
7
  const MODIFIER_KEYS = ['meta', 'alt', 'shift', 'control'];
8
8
  const modifierKeysObserver = createKeysObserver();
9
+ const modKeyListeners = [];
9
10
  let instanceCounter = 0;
10
11
 
11
12
  /* eslint-disable jsdoc/require-description-complete-sentence */
@@ -104,9 +105,11 @@ export function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDow
104
105
  * @param {KeyboardEvent} event The event object
105
106
  */
106
107
  const onkeydownForModKeys = event => {
107
- const pressedKey = normalizeEventKey(event);
108
- if (isModifierKey(pressedKey)) {
109
- modifierKeysObserver.press(pressedKey);
108
+ if (event.key) {
109
+ const pressedKey = normalizeEventKey(event);
110
+ if (isModifierKey(pressedKey)) {
111
+ modifierKeysObserver.press(pressedKey);
112
+ }
110
113
  }
111
114
  };
112
115
 
@@ -117,9 +120,11 @@ export function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDow
117
120
  * @param {KeyboardEvent} event The event object
118
121
  */
119
122
  const onkeyupForModKeys = event => {
120
- const pressedKey = normalizeEventKey(event);
121
- if (isModifierKey(pressedKey)) {
122
- modifierKeysObserver.release(pressedKey);
123
+ if (event.key) {
124
+ const pressedKey = normalizeEventKey(event);
125
+ if (isModifierKey(pressedKey)) {
126
+ modifierKeysObserver.release(pressedKey);
127
+ }
123
128
  }
124
129
  };
125
130
 
@@ -141,7 +146,15 @@ export function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDow
141
146
  while (eventTarget) {
142
147
  if (instanceCounter === 1) {
143
148
  eventTarget.document.documentElement.addEventListener('keydown', onkeydownForModKeys);
149
+ modKeyListeners.push({
150
+ event: 'keydown',
151
+ listener: onkeydownForModKeys
152
+ });
144
153
  eventTarget.document.documentElement.addEventListener('keyup', onkeyupForModKeys);
154
+ modKeyListeners.push({
155
+ event: 'keyup',
156
+ listener: onkeyupForModKeys
157
+ });
145
158
  }
146
159
  eventTarget.document.documentElement.addEventListener('keydown', onkeydown);
147
160
  eventTarget.document.documentElement.addEventListener('blur', onblur);
@@ -157,8 +170,14 @@ export function useRecorder(ownerWindow, handleEvent, beforeKeyDown, afterKeyDow
157
170
  instanceCounter -= 1;
158
171
  while (eventTarget) {
159
172
  if (instanceCounter === 0) {
160
- eventTarget.document.documentElement.removeEventListener('keydown', onkeydownForModKeys);
161
- eventTarget.document.documentElement.removeEventListener('keyup', onkeyupForModKeys);
173
+ for (let i = 0; i < modKeyListeners.length; i++) {
174
+ const {
175
+ event,
176
+ listener
177
+ } = modKeyListeners[i];
178
+ eventTarget.document.documentElement.removeEventListener(event, listener);
179
+ }
180
+ modKeyListeners.length = 0;
162
181
  }
163
182
  eventTarget.document.documentElement.removeEventListener('keydown', onkeydown);
164
183
  eventTarget.document.documentElement.removeEventListener('blur', onblur);
package/tableView.js CHANGED
@@ -307,15 +307,13 @@ class TableView {
307
307
  const {
308
308
  rootElement,
309
309
  rootDocument,
310
- selection
310
+ selection,
311
+ rootWindow
311
312
  } = this.hot;
312
313
  const documentElement = rootDocument.documentElement;
313
314
  this.eventManager.addEventListener(rootElement, 'mousedown', event => {
314
315
  _classPrivateFieldSet(this, _selectionMouseDown, true);
315
316
  if (!this.isTextSelectionAllowed(event.target)) {
316
- const {
317
- rootWindow
318
- } = this.hot;
319
317
  (0, _element.clearTextSelection)(rootWindow);
320
318
  event.preventDefault();
321
319
  rootWindow.focus(); // make sure that window that contains HOT is active. Important when HOT is in iframe.
@@ -328,7 +326,7 @@ class TableView {
328
326
  if (_classPrivateFieldGet(this, _selectionMouseDown) && !this.isTextSelectionAllowed(event.target)) {
329
327
  // Clear selection only when fragmentSelection is enabled, otherwise clearing selection breaks the IME editor.
330
328
  if (this.settings.fragmentSelection) {
331
- (0, _element.clearTextSelection)(this.hot.rootWindow);
329
+ (0, _element.clearTextSelection)(rootWindow);
332
330
  }
333
331
  event.preventDefault();
334
332
  }
@@ -408,6 +406,13 @@ class TableView {
408
406
  this.hot.destroyEditor(false, false);
409
407
  }
410
408
  });
409
+ let parentWindow = (0, _element.getParentWindow)(rootWindow);
410
+ while (parentWindow !== null) {
411
+ this.eventManager.addEventListener(parentWindow.document.documentElement, 'click', () => {
412
+ this.hot.unlisten();
413
+ });
414
+ parentWindow = (0, _element.getParentWindow)(parentWindow);
415
+ }
411
416
  this.eventManager.addEventListener(_classPrivateFieldGet(this, _table), 'selectstart', event => {
412
417
  if (this.settings.fragmentSelection || (0, _element.isInput)(event.target)) {
413
418
  return;
@@ -1310,6 +1315,42 @@ class TableView {
1310
1315
  return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getLastVisibleColumn());
1311
1316
  }
1312
1317
 
1318
+ /**
1319
+ * Returns the first partially visible row in the table viewport.
1320
+ *
1321
+ * @returns {number}
1322
+ */
1323
+ getFirstPartiallyVisibleRow() {
1324
+ return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getFirstPartiallyVisibleRow());
1325
+ }
1326
+
1327
+ /**
1328
+ * Returns the last partially visible row in the table viewport.
1329
+ *
1330
+ * @returns {number}
1331
+ */
1332
+ getLastPartiallyVisibleRow() {
1333
+ return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getLastPartiallyVisibleRow());
1334
+ }
1335
+
1336
+ /**
1337
+ * Returns the first partially visible column in the table viewport.
1338
+ *
1339
+ * @returns {number}
1340
+ */
1341
+ getFirstPartiallyVisibleColumn() {
1342
+ return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getFirstPartiallyVisibleColumn());
1343
+ }
1344
+
1345
+ /**
1346
+ * Returns the last partially visible column in the table viewport.
1347
+ *
1348
+ * @returns {number}
1349
+ */
1350
+ getLastPartiallyVisibleColumn() {
1351
+ return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getLastPartiallyVisibleColumn());
1352
+ }
1353
+
1313
1354
  /**
1314
1355
  * Returns the total count of the rendered column headers.
1315
1356
  *
@@ -1327,6 +1368,46 @@ class TableView {
1327
1368
  getRowHeadersCount() {
1328
1369
  return _classPrivateFieldGet(this, _rowHeadersCount);
1329
1370
  }
1371
+
1372
+ /**
1373
+ * Returns the table's viewport width. When the table has defined the size of the container,
1374
+ * and the columns do not fill the entire viewport, the viewport width is equal to the sum of
1375
+ * the columns' widths.
1376
+ *
1377
+ * @returns {number}
1378
+ */
1379
+ getViewportWidth() {
1380
+ return this.hot.view._wt.wtViewport.getViewportWidth();
1381
+ }
1382
+
1383
+ /**
1384
+ * Returns the table's total width including the scrollbar width.
1385
+ *
1386
+ * @returns {number}
1387
+ */
1388
+ getWorkspaceWidth() {
1389
+ return this.hot.view._wt.wtViewport.getWorkspaceWidth();
1390
+ }
1391
+
1392
+ /**
1393
+ * Returns the table's viewport height. When the table has defined the size of the container,
1394
+ * and the rows do not fill the entire viewport, the viewport height is equal to the sum of
1395
+ * the rows' heights.
1396
+ *
1397
+ * @returns {number}
1398
+ */
1399
+ getViewportHeight() {
1400
+ return this.hot.view._wt.wtViewport.getViewportHeight();
1401
+ }
1402
+
1403
+ /**
1404
+ * Returns the table's total height including the scrollbar height.
1405
+ *
1406
+ * @returns {number}
1407
+ */
1408
+ getWorkspaceHeight() {
1409
+ return this.hot.view._wt.wtViewport.getWorkspaceHeight();
1410
+ }
1330
1411
  /**
1331
1412
  * Destroys internal WalkOnTable's instance. Detaches all of the bonded listeners.
1332
1413
  *
package/tableView.mjs CHANGED
@@ -12,7 +12,7 @@ function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) {
12
12
  function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
13
13
  function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
14
14
  function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
15
- import { addClass, clearTextSelection, empty, fastInnerHTML, fastInnerText, getScrollbarWidth, hasClass, isChildOf, isInput, isOutsideInput, isVisible, setAttribute } from "./helpers/dom/element.mjs";
15
+ import { addClass, clearTextSelection, empty, fastInnerHTML, fastInnerText, getScrollbarWidth, hasClass, isChildOf, isInput, isOutsideInput, isVisible, setAttribute, getParentWindow } from "./helpers/dom/element.mjs";
16
16
  import EventManager from "./eventManager.mjs";
17
17
  import { isImmediatePropagationStopped, isRightClick, isLeftClick } from "./helpers/dom/event.mjs";
18
18
  import Walkontable from "./3rdparty/walkontable/src/index.mjs";
@@ -303,15 +303,13 @@ class TableView {
303
303
  const {
304
304
  rootElement,
305
305
  rootDocument,
306
- selection
306
+ selection,
307
+ rootWindow
307
308
  } = this.hot;
308
309
  const documentElement = rootDocument.documentElement;
309
310
  this.eventManager.addEventListener(rootElement, 'mousedown', event => {
310
311
  _classPrivateFieldSet(this, _selectionMouseDown, true);
311
312
  if (!this.isTextSelectionAllowed(event.target)) {
312
- const {
313
- rootWindow
314
- } = this.hot;
315
313
  clearTextSelection(rootWindow);
316
314
  event.preventDefault();
317
315
  rootWindow.focus(); // make sure that window that contains HOT is active. Important when HOT is in iframe.
@@ -324,7 +322,7 @@ class TableView {
324
322
  if (_classPrivateFieldGet(this, _selectionMouseDown) && !this.isTextSelectionAllowed(event.target)) {
325
323
  // Clear selection only when fragmentSelection is enabled, otherwise clearing selection breaks the IME editor.
326
324
  if (this.settings.fragmentSelection) {
327
- clearTextSelection(this.hot.rootWindow);
325
+ clearTextSelection(rootWindow);
328
326
  }
329
327
  event.preventDefault();
330
328
  }
@@ -404,6 +402,13 @@ class TableView {
404
402
  this.hot.destroyEditor(false, false);
405
403
  }
406
404
  });
405
+ let parentWindow = getParentWindow(rootWindow);
406
+ while (parentWindow !== null) {
407
+ this.eventManager.addEventListener(parentWindow.document.documentElement, 'click', () => {
408
+ this.hot.unlisten();
409
+ });
410
+ parentWindow = getParentWindow(parentWindow);
411
+ }
407
412
  this.eventManager.addEventListener(_classPrivateFieldGet(this, _table), 'selectstart', event => {
408
413
  if (this.settings.fragmentSelection || isInput(event.target)) {
409
414
  return;
@@ -1306,6 +1311,42 @@ class TableView {
1306
1311
  return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getLastVisibleColumn());
1307
1312
  }
1308
1313
 
1314
+ /**
1315
+ * Returns the first partially visible row in the table viewport.
1316
+ *
1317
+ * @returns {number}
1318
+ */
1319
+ getFirstPartiallyVisibleRow() {
1320
+ return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getFirstPartiallyVisibleRow());
1321
+ }
1322
+
1323
+ /**
1324
+ * Returns the last partially visible row in the table viewport.
1325
+ *
1326
+ * @returns {number}
1327
+ */
1328
+ getLastPartiallyVisibleRow() {
1329
+ return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getLastPartiallyVisibleRow());
1330
+ }
1331
+
1332
+ /**
1333
+ * Returns the first partially visible column in the table viewport.
1334
+ *
1335
+ * @returns {number}
1336
+ */
1337
+ getFirstPartiallyVisibleColumn() {
1338
+ return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getFirstPartiallyVisibleColumn());
1339
+ }
1340
+
1341
+ /**
1342
+ * Returns the last partially visible column in the table viewport.
1343
+ *
1344
+ * @returns {number}
1345
+ */
1346
+ getLastPartiallyVisibleColumn() {
1347
+ return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this.hot.view._wt.wtScroll.getLastPartiallyVisibleColumn());
1348
+ }
1349
+
1309
1350
  /**
1310
1351
  * Returns the total count of the rendered column headers.
1311
1352
  *
@@ -1323,6 +1364,46 @@ class TableView {
1323
1364
  getRowHeadersCount() {
1324
1365
  return _classPrivateFieldGet(this, _rowHeadersCount);
1325
1366
  }
1367
+
1368
+ /**
1369
+ * Returns the table's viewport width. When the table has defined the size of the container,
1370
+ * and the columns do not fill the entire viewport, the viewport width is equal to the sum of
1371
+ * the columns' widths.
1372
+ *
1373
+ * @returns {number}
1374
+ */
1375
+ getViewportWidth() {
1376
+ return this.hot.view._wt.wtViewport.getViewportWidth();
1377
+ }
1378
+
1379
+ /**
1380
+ * Returns the table's total width including the scrollbar width.
1381
+ *
1382
+ * @returns {number}
1383
+ */
1384
+ getWorkspaceWidth() {
1385
+ return this.hot.view._wt.wtViewport.getWorkspaceWidth();
1386
+ }
1387
+
1388
+ /**
1389
+ * Returns the table's viewport height. When the table has defined the size of the container,
1390
+ * and the rows do not fill the entire viewport, the viewport height is equal to the sum of
1391
+ * the rows' heights.
1392
+ *
1393
+ * @returns {number}
1394
+ */
1395
+ getViewportHeight() {
1396
+ return this.hot.view._wt.wtViewport.getViewportHeight();
1397
+ }
1398
+
1399
+ /**
1400
+ * Returns the table's total height including the scrollbar height.
1401
+ *
1402
+ * @returns {number}
1403
+ */
1404
+ getWorkspaceHeight() {
1405
+ return this.hot.view._wt.wtViewport.getWorkspaceHeight();
1406
+ }
1326
1407
  /**
1327
1408
  * Destroys internal WalkOnTable's instance. Detaches all of the bonded listeners.
1328
1409
  *
@@ -180,7 +180,6 @@ function createInputElementResizer(ownerDocument) {
180
180
  extendDefaults(config);
181
181
  if (observedElement.nodeName === 'TEXTAREA') {
182
182
  observedElement.style.resize = 'none';
183
- observedElement.style.overflowY = '';
184
183
  observedElement.style.height = `${defaults.minHeight}px`;
185
184
  observedElement.style.minWidth = `${defaults.minWidth}px`;
186
185
  observedElement.style.maxWidth = `${defaults.maxWidth}px`;
@@ -176,7 +176,6 @@ export function createInputElementResizer(ownerDocument) {
176
176
  extendDefaults(config);
177
177
  if (observedElement.nodeName === 'TEXTAREA') {
178
178
  observedElement.style.resize = 'none';
179
- observedElement.style.overflowY = '';
180
179
  observedElement.style.height = `${defaults.minHeight}px`;
181
180
  observedElement.style.minWidth = `${defaults.minWidth}px`;
182
181
  observedElement.style.maxWidth = `${defaults.maxWidth}px`;