handsontable 14.1.0 → 14.2.0-next-4873a35-20240228

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) 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 +2996 -1928
  52. package/dist/handsontable.full.min.css +2 -2
  53. package/dist/handsontable.full.min.js +42 -42
  54. package/dist/handsontable.js +2998 -1930
  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/dropdownMenu/dropdownMenu.js +58 -4
  105. package/plugins/dropdownMenu/dropdownMenu.mjs +58 -4
  106. package/plugins/filters/component/value.js +51 -5
  107. package/plugins/filters/component/value.mjs +51 -5
  108. package/plugins/filters/utils.js +1 -1
  109. package/plugins/filters/utils.mjs +1 -1
  110. package/plugins/formulas/formulas.js +10 -1
  111. package/plugins/formulas/formulas.mjs +10 -1
  112. package/plugins/formulas/indexSyncer/axisSyncer.js +3 -75
  113. package/plugins/formulas/indexSyncer/axisSyncer.mjs +3 -75
  114. package/plugins/manualColumnResize/manualColumnResize.js +3 -0
  115. package/plugins/manualColumnResize/manualColumnResize.mjs +3 -0
  116. package/plugins/mergeCells/cellsCollection.js +1 -1
  117. package/plugins/mergeCells/cellsCollection.mjs +1 -1
  118. package/plugins/mergeCells/mergeCells.js +30 -0
  119. package/plugins/mergeCells/mergeCells.mjs +30 -0
  120. package/plugins/undoRedo/undoRedo.js +61 -14
  121. package/plugins/undoRedo/undoRedo.mjs +61 -14
  122. package/renderers/autocompleteRenderer/autocompleteRenderer.js +1 -1
  123. package/renderers/autocompleteRenderer/autocompleteRenderer.mjs +1 -1
  124. package/renderers/baseRenderer/baseRenderer.js +1 -1
  125. package/renderers/baseRenderer/baseRenderer.mjs +1 -1
  126. package/renderers/checkboxRenderer/checkboxRenderer.js +36 -8
  127. package/renderers/checkboxRenderer/checkboxRenderer.mjs +36 -8
  128. package/renderers/dateRenderer/dateRenderer.js +1 -1
  129. package/renderers/dateRenderer/dateRenderer.mjs +1 -1
  130. package/renderers/dropdownRenderer/dropdownRenderer.js +1 -1
  131. package/renderers/dropdownRenderer/dropdownRenderer.mjs +1 -1
  132. package/renderers/handsontableRenderer/handsontableRenderer.js +1 -1
  133. package/renderers/handsontableRenderer/handsontableRenderer.mjs +1 -1
  134. package/renderers/htmlRenderer/htmlRenderer.js +1 -1
  135. package/renderers/htmlRenderer/htmlRenderer.mjs +1 -1
  136. package/renderers/numericRenderer/index.js +2 -1
  137. package/renderers/numericRenderer/index.mjs +1 -1
  138. package/renderers/numericRenderer/numericRenderer.js +28 -13
  139. package/renderers/numericRenderer/numericRenderer.mjs +27 -13
  140. package/renderers/passwordRenderer/passwordRenderer.js +1 -1
  141. package/renderers/passwordRenderer/passwordRenderer.mjs +1 -1
  142. package/renderers/selectRenderer/selectRenderer.js +1 -1
  143. package/renderers/selectRenderer/selectRenderer.mjs +1 -1
  144. package/renderers/textRenderer/textRenderer.js +1 -1
  145. package/renderers/textRenderer/textRenderer.mjs +1 -1
  146. package/renderers/timeRenderer/timeRenderer.js +1 -1
  147. package/renderers/timeRenderer/timeRenderer.mjs +1 -1
  148. package/selection/mouseEventHandler.js +4 -0
  149. package/selection/mouseEventHandler.mjs +4 -0
  150. package/selection/selection.js +64 -5
  151. package/selection/selection.mjs +64 -5
  152. package/shortcuts/recorder.js +27 -8
  153. package/shortcuts/recorder.mjs +27 -8
  154. package/tableView.js +86 -5
  155. package/tableView.mjs +87 -6
  156. package/utils/autoResize.js +0 -1
  157. package/utils/autoResize.mjs +0 -1
  158. package/utils/ghostTable.js +6 -6
  159. package/utils/ghostTable.mjs +6 -6
  160. package/utils/parseTable.js +9 -1
  161. 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`;