handsontable 18.1.0-rc8 → 18.1.0

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 (74) hide show
  1. package/3rdparty/walkontable/src/event.d.ts +17 -0
  2. package/3rdparty/walkontable/src/event.js +188 -21
  3. package/3rdparty/walkontable/src/event.mjs +188 -21
  4. package/CHANGELOG.md +7 -30
  5. package/base.js +2 -2
  6. package/base.mjs +2 -2
  7. package/dist/handsontable.full.js +2263 -2011
  8. package/dist/handsontable.full.min.js +117 -117
  9. package/dist/handsontable.js +2262 -2011
  10. package/dist/handsontable.min.js +117 -117
  11. package/dist/themes/classic.js +2 -2
  12. package/dist/themes/classic.min.js +2 -2
  13. package/dist/themes/horizon.js +2 -2
  14. package/dist/themes/horizon.min.js +2 -2
  15. package/dist/themes/main.js +2 -2
  16. package/dist/themes/main.min.js +2 -2
  17. package/dist/themes/static/variables/colors/ant.js +2 -2
  18. package/dist/themes/static/variables/colors/ant.min.js +2 -2
  19. package/dist/themes/static/variables/colors/classic.js +2 -2
  20. package/dist/themes/static/variables/colors/classic.min.js +2 -2
  21. package/dist/themes/static/variables/colors/horizon.js +2 -2
  22. package/dist/themes/static/variables/colors/horizon.min.js +2 -2
  23. package/dist/themes/static/variables/colors/main.js +2 -2
  24. package/dist/themes/static/variables/colors/main.min.js +2 -2
  25. package/dist/themes/static/variables/colors/material.js +2 -2
  26. package/dist/themes/static/variables/colors/material.min.js +2 -2
  27. package/dist/themes/static/variables/colors/shadcn.js +2 -2
  28. package/dist/themes/static/variables/colors/shadcn.min.js +2 -2
  29. package/dist/themes/static/variables/density.js +2 -2
  30. package/dist/themes/static/variables/density.min.js +2 -2
  31. package/dist/themes/static/variables/helpers/iconsMap.js +2 -2
  32. package/dist/themes/static/variables/helpers/iconsMap.min.js +2 -2
  33. package/dist/themes/static/variables/icons/horizon.js +2 -2
  34. package/dist/themes/static/variables/icons/horizon.min.js +2 -2
  35. package/dist/themes/static/variables/icons/main.js +2 -2
  36. package/dist/themes/static/variables/icons/main.min.js +2 -2
  37. package/dist/themes/static/variables/sizing.js +2 -2
  38. package/dist/themes/static/variables/sizing.min.js +2 -2
  39. package/dist/themes/static/variables/tokens/classic.js +2 -2
  40. package/dist/themes/static/variables/tokens/classic.min.js +2 -2
  41. package/dist/themes/static/variables/tokens/horizon.js +2 -2
  42. package/dist/themes/static/variables/tokens/horizon.min.js +2 -2
  43. package/dist/themes/static/variables/tokens/main.js +2 -2
  44. package/dist/themes/static/variables/tokens/main.min.js +2 -2
  45. package/helpers/dom/inputOrigin.d.mts +1 -0
  46. package/helpers/dom/inputOrigin.d.ts +38 -0
  47. package/helpers/dom/inputOrigin.js +54 -0
  48. package/helpers/dom/inputOrigin.mjs +48 -0
  49. package/helpers/mixed.js +20 -5
  50. package/helpers/mixed.mjs +20 -5
  51. package/package.json +1 -1
  52. package/styles/handsontable.css +2 -2
  53. package/styles/handsontable.min.css +2 -2
  54. package/styles/handsontableStyles.js +1 -1
  55. package/styles/handsontableStyles.mjs +1 -1
  56. package/styles/ht-icons-horizon.min.css +2 -2
  57. package/styles/ht-icons-main.min.css +2 -2
  58. package/styles/ht-theme-classic-no-icons.min.css +2 -2
  59. package/styles/ht-theme-classic.min.css +2 -2
  60. package/styles/ht-theme-horizon-no-icons.min.css +2 -2
  61. package/styles/ht-theme-horizon.min.css +2 -2
  62. package/styles/ht-theme-main-no-icons.min.css +2 -2
  63. package/styles/ht-theme-main.min.css +2 -2
  64. package/tableView.js +16 -12
  65. package/tableView.mjs +16 -12
  66. package/utils/entitlementLicenseKey/constants.d.ts +9 -3
  67. package/utils/entitlementLicenseKey/constants.mjs +9 -3
  68. package/utils/entitlementLicenseKey/types.d.ts +9 -3
  69. package/utils/licenseBranding/index.js +22 -7
  70. package/utils/licenseBranding/index.mjs +22 -7
  71. package/utils/licenseNotification.js +2 -2
  72. package/utils/licenseNotification.mjs +2 -2
  73. package/styles/handsontableStyles.d.mts +0 -2
  74. package/styles/handsontableStyles.d.ts +0 -2
@@ -52,8 +52,23 @@ import { closestDown, eventTargetEl, getDeepActiveElement, hasClass, isChildOf,
52
52
  import { getCellCoordsFromMousePosition } from './utils/pointerToCoords.mjs';
53
53
  import { isTouchSupported } from '../../../helpers/feature.mjs';
54
54
  import { isMobileBrowser, isChromeWebKit, isFirefoxWebKit, isIOS } from '../../../helpers/browser.mjs';
55
+ import { getMouseEventTouchOrigin, TOUCH_SYNTHESIZED_MOUSE_WINDOW } from '../../../helpers/dom/inputOrigin.mjs';
55
56
  const LONG_PRESS_DELAY = 500;
56
57
  const LONG_PRESS_MOVE_THRESHOLD = 10;
58
+ /**
59
+ * How long (ms) after a mousedown the double-click detector keeps waiting for the matching
60
+ * second click. Mirrors the OS double-click tolerance with margin.
61
+ */ const DBLCLICK_MOUSEDOWN_TIMEOUT = 1000;
62
+ /**
63
+ * How long (ms) after a mouseup the double-click detector keeps the first click "armed"
64
+ * for a mouse-driven double-click.
65
+ */ const DBLCLICK_MOUSEUP_TIMEOUT = 500;
66
+ /**
67
+ * How long (ms) after a touch tap a second tap on the same cell counts as a double-tap. Touch
68
+ * taps are paired by `#handleTouchTap()`, independently of the mouse double-click slots, so a
69
+ * real mouse click after a tap never pairs with it. iOS drops taps under ~250 ms and humans
70
+ * double-tap at 300–600 ms (DEV-2687).
71
+ */ const TOUCH_DBLTAP_TIMEOUT = 1000;
57
72
  /**
58
73
  * Assembles the Event module's dependencies from the engine composition context. The DOM roots,
59
74
  * settings, event manager, table, and selection manager fold into this one object; the parent Event
@@ -88,6 +103,17 @@ var /**
88
103
  */ _dblClickTimeout = /*#__PURE__*/ new WeakMap(), /**
89
104
  * @type {number[]}
90
105
  */ _dblClickOrigin = /*#__PURE__*/ new WeakMap(), /**
106
+ * Coordinates of the most recent touch tap, kept for double-tap detection. Coordinates, not the
107
+ * resolved TD: Walkontable recycles TD elements across scrolls and re-renders, so element
108
+ * identity can pair two taps that landed on different cells (DEV-2687 review). Touch taps never
109
+ * arm the mouse double-click slots, so a mouse click after a tap cannot pair with a tap.
110
+ *
111
+ * @type {CellCoords|null}
112
+ */ _lastTapCoords = /*#__PURE__*/ new WeakMap(), /**
113
+ * Timestamp (ms) of the most recent touch tap.
114
+ *
115
+ * @type {number}
116
+ */ _lastTapAt = /*#__PURE__*/ new WeakMap(), /**
91
117
  * Timer ID for the long-press gesture detection.
92
118
  *
93
119
  * @type {number|null}
@@ -112,12 +138,25 @@ var /**
112
138
  * @type {TouchEvent|null}
113
139
  */ _deferredTouchStartEvent = /*#__PURE__*/ new WeakMap(), /**
114
140
  * Timestamp (ms) of the most recent `onMouseUp` call that originated from a touch gesture.
115
- * Used to suppress the browser-synthesized `mouseup` event that fires after `touchend` on
116
- * devices that register both touch and mouse listeners (e.g. iPad Safari), which would
117
- * otherwise trigger `onCellMouseUp` — and context-menu commands — a second time.
141
+ * On devices that register both touch and mouse listeners (iPad with a desktop UA, Windows
142
+ * touchscreens) the browser synthesizes a `mousedown`/`mouseup`/`click` sequence after
143
+ * `touchend`. The whole sequence must be ignored – dropping only one half fires
144
+ * `onCellMouseDown` a second time per tap, and the leaked pair would act as a phantom mouse
145
+ * click (DEV-2687).
146
+ * Used as the fallback for engines that do not expose `sourceCapabilities`
147
+ * (see `#isTouchSynthesizedMouseEvent`).
118
148
  *
119
149
  * @type {number}
120
150
  */ _lastTouchMouseUpAt = /*#__PURE__*/ new WeakMap(), /**
151
+ * `true` between a touch-driven `onMouseUp` and the browser-synthesized `mouseup` that follows it.
152
+ * Only that first pair is dropped; once it is consumed, real mouse events pass even inside the
153
+ * `TOUCH_SYNTHESIZED_MOUSE_WINDOW` ceiling, so a fill-handle drag or a drag-selection started with
154
+ * a mouse right after a tap works on engines that do not report the input origin (DEV-2687). The
155
+ * flag is re-armed by every touch-driven `onMouseUp` and cleared when a scroll-classified gesture
156
+ * ends, so a tap that synthesized nothing cannot swallow that gesture's own compatibility pair.
157
+ *
158
+ * @type {boolean}
159
+ */ _synthesizedPairPending = /*#__PURE__*/ new WeakMap(), /**
121
160
  * @type {boolean}
122
161
  */ _mouseDown = /*#__PURE__*/ new WeakMap(), /**
123
162
  * The last renderable coords seen in `onMouseMove` while the mouse was outside the viewport.
@@ -126,6 +165,18 @@ var /**
126
165
  *
127
166
  * @type {{ row: number, col: number } | null}
128
167
  */ _mouseOverOutsideLastCoords = /*#__PURE__*/ new WeakMap(), /**
168
+ * Decides whether a mouse event caught by the mouse listeners is one half of the browser-synthesized
169
+ * `mousedown`/`mouseup` pair that follows a touch tap, and must therefore be dropped. Order of the
170
+ * checks: an engine that reports the input origin and says "not touch" wins (Blink, a real mouse or
171
+ * pen is never dropped); otherwise the event is synthesized only if a touch-driven `onMouseUp` just
172
+ * armed the pair (`#synthesizedPairPending`) and the ceiling has not passed. The `mouseup` half
173
+ * consumes the pair, so any later mouse event inside the ceiling is treated as real. Dropping both
174
+ * halves keeps `onCellMouseDown` at one call per tap and context-menu commands at one execution
175
+ * (#12803); a tap that left no stamp (a gesture treated as a scroll) has its pair processed.
176
+ *
177
+ * @param {MouseEvent} event The mouse event object.
178
+ * @returns {boolean}
179
+ */ _isTouchSynthesizedMouseEvent = /*#__PURE__*/ new WeakSet(), /**
129
180
  * Returns the cell coordinates for the given mouse position and whether the mouse is
130
181
  * outside the visible viewport. When the mouse is outside, the nearest edge cell is returned.
131
182
  *
@@ -134,6 +185,19 @@ var /**
134
185
  * @param {number} mouseY Client Y coordinate of the mouse.
135
186
  * @returns {{ coords: CellCoords, isOutside: boolean }}
136
187
  */ _getCellCoordsFromMousePosition = /*#__PURE__*/ new WeakSet(), /**
188
+ * Pairs touch taps into double-taps. Called from `onMouseUp` while `touchApplied` is `true`,
189
+ * i.e. for the `onMouseUp` that `onTouchEnd` drives. Two taps on the same coordinates within
190
+ * `TOUCH_DBLTAP_TIMEOUT` fire the double-click callbacks; a long-press, a tap outside the cells,
191
+ * or a tap on different coordinates resets the detector.
192
+ *
193
+ * @param {MouseEvent|TouchEvent} event The event that ended the tap.
194
+ * @param {ParentCell} cell The tapped cell, as returned by `parentCell()`.
195
+ */ _handleTouchTap = /*#__PURE__*/ new WeakSet(), /**
196
+ * Fires the corner or the cell double-click callback for the given cell.
197
+ *
198
+ * @param {MouseEvent|TouchEvent} event The event that completed the double-click.
199
+ * @param {ParentCell} cell The double-clicked cell.
200
+ */ _fireDblClick = /*#__PURE__*/ new WeakSet(), /**
137
201
  * Starts the long-press timer. When the timer fires, a synthetic `contextmenu` event is
138
202
  * dispatched on the original touch target so that the existing contextmenu hook chain
139
203
  * (and ContextMenu plugin) work without changes.
@@ -167,20 +231,27 @@ var /**
167
231
  _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'touchstart', (event)=>this.onTouchStart(event));
168
232
  _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'touchend', (event)=>this.onTouchEnd(event));
169
233
  _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'touchmove', (event)=>this.onTouchMove(event));
234
+ _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'touchcancel', ()=>this.onTouchCancel());
170
235
  _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'scroll', ()=>this.onHolderScroll());
171
236
  };
172
237
  const initMouseEvents = ()=>{
238
+ // On devices that register both touch and mouse listeners (e.g. iPad Safari with a
239
+ // desktop UA), `touchend` already drove `onMouseDown`/`onMouseUp`. The browser then
240
+ // synthesizes a `mousedown`/`mouseup` pair ~0-50 ms later; drop BOTH halves when the
241
+ // touch path handled the tap, so `onCellMouseDown` fires once per tap (DEV-2687) and
242
+ // context-menu commands do not execute twice (#12803).
173
243
  _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'mouseup', (event)=>{
174
- // On devices that register both touch and mouse listeners (e.g. iPad Safari),
175
- // `touchend` fires first and calls `onMouseUp` directly. The browser then
176
- // synthesizes a `mouseup` event ~0-50 ms later; suppress it to prevent
177
- // context-menu commands from executing twice.
178
- if (Date.now() - _class_private_field_get(this, _lastTouchMouseUpAt) < 500) {
244
+ if (_class_private_method_get(this, _isTouchSynthesizedMouseEvent, isTouchSynthesizedMouseEvent).call(this, event)) {
179
245
  return;
180
246
  }
181
247
  this.onMouseUp(event);
182
248
  });
183
- _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'mousedown', (event)=>this.onMouseDown(event));
249
+ _class_private_field_get(this, _deps).eventManager.addEventListener(_class_private_field_get(this, _deps).wtTable.holder, 'mousedown', (event)=>{
250
+ if (_class_private_method_get(this, _isTouchSynthesizedMouseEvent, isTouchSynthesizedMouseEvent).call(this, event)) {
251
+ return;
252
+ }
253
+ this.onMouseDown(event);
254
+ });
184
255
  };
185
256
  if (isMobileBrowser()) {
186
257
  initTouchEvents();
@@ -277,15 +348,16 @@ var /**
277
348
  this.callListener('onCellMouseDown', event, cell.coords, cell.TD);
278
349
  }
279
350
  }
280
- // doubleclick reacts only for left mouse button or from touch events
281
- if ((event.button === 0 || this.touchApplied) && cell.TD) {
351
+ // The mouse double-click slots are armed by mouse clicks only; touch taps are paired by
352
+ // #handleTouchTap() in onMouseUp (DEV-2687).
353
+ if (!this.touchApplied && event.button === 0 && cell.TD) {
282
354
  _class_private_field_get(this, _dblClickOrigin)[0] = cell.TD;
283
355
  if (_class_private_field_get(this, _dblClickTimeout)[0] !== null) {
284
356
  clearTimeout(_class_private_field_get(this, _dblClickTimeout)[0]);
285
357
  }
286
358
  _class_private_field_get(this, _dblClickTimeout)[0] = setTimeout(()=>{
287
359
  _class_private_field_get(this, _dblClickOrigin)[0] = null;
288
- }, 1000);
360
+ }, DBLCLICK_MOUSEDOWN_TIMEOUT);
289
361
  }
290
362
  }
291
363
  /**
@@ -394,16 +466,16 @@ var /**
394
466
  if (cell.TD && _class_private_field_get(this, _deps).wtSettings.has('onCellMouseUp')) {
395
467
  this.callListener('onCellMouseUp', event, cell.coords, cell.TD);
396
468
  }
397
- // if not left mouse button, and the origin event is not comes from touch
398
- if (event.button !== 0 && !this.touchApplied) {
469
+ if (this.touchApplied) {
470
+ _class_private_method_get(this, _handleTouchTap, handleTouchTap).call(this, event, cell);
471
+ return;
472
+ }
473
+ // ignore non-left mouse buttons
474
+ if (event.button !== 0) {
399
475
  return;
400
476
  }
401
477
  if (cell.TD && cell.TD === _class_private_field_get(this, _dblClickOrigin)[0] && cell.TD === _class_private_field_get(this, _dblClickOrigin)[1]) {
402
- if (hasClass(eventTargetEl(event), 'corner')) {
403
- this.callListener('onCellCornerDblClick', event, cell.coords, cell.TD);
404
- } else {
405
- this.callListener('onCellDblClick', event, cell.coords, cell.TD);
406
- }
478
+ _class_private_method_get(this, _fireDblClick, fireDblClick).call(this, event, cell);
407
479
  _class_private_field_get(this, _dblClickOrigin)[0] = null;
408
480
  _class_private_field_get(this, _dblClickOrigin)[1] = null;
409
481
  } else if (cell.TD && cell.TD === _class_private_field_get(this, _dblClickOrigin)[0]) {
@@ -413,7 +485,7 @@ var /**
413
485
  }
414
486
  _class_private_field_get(this, _dblClickTimeout)[1] = setTimeout(()=>{
415
487
  _class_private_field_get(this, _dblClickOrigin)[1] = null;
416
- }, 500);
488
+ }, DBLCLICK_MOUSEUP_TIMEOUT);
417
489
  }
418
490
  }
419
491
  /**
@@ -483,14 +555,51 @@ var /**
483
555
  // before/after hooks (e.g. nestedHeaders, ContextMenu close logic).
484
556
  // Suppress only for pure scroll gestures, where onMouseDown was never fired.
485
557
  if (!wasScrolled || _class_private_field_get(this, _longPressFired)) {
486
- _class_private_field_set(this, _lastTouchMouseUpAt, Date.now());
558
+ // The stamp is taken AFTER the tap is handled, so the selection/render work onMouseUp does
559
+ // is not charged against the TOUCH_SYNTHESIZED_MOUSE_WINDOW ceiling. Everything onMouseUp
560
+ // triggers is synchronous; the browser only dispatches the synthesized mousedown/mouseup
561
+ // sequence after this touchend handler returns.
487
562
  this.onMouseUp(event);
563
+ _class_private_field_set(this, _lastTouchMouseUpAt, Date.now());
564
+ _class_private_field_set(this, _synthesizedPairPending, true);
565
+ } else {
566
+ // A pure scroll gesture calls neither onMouseDown nor onMouseUp, so #handleTouchTap never
567
+ // runs to reset the tap detector. Reset it here so a scroll between two taps can't pair them.
568
+ _class_private_field_set(this, _lastTapCoords, null);
569
+ // This gesture armed nothing, so a still-pending flag belongs to an earlier gesture whose
570
+ // pair never came; clear it so THIS gesture's compatibility pair is processed.
571
+ _class_private_field_set(this, _synthesizedPairPending, false);
488
572
  }
489
573
  this.touchApplied = false;
490
574
  _class_private_field_set(this, _touchWasMoved, false);
491
575
  _class_private_field_set(this, _longPressFired, false);
492
576
  }
493
577
  /**
578
+ * OnTouchCancel callback. Browsers cancel a gesture instead of ending it whenever the system
579
+ * claims the touch (an edge-swipe, a dialog, a context callout) — `touchend` then never fires.
580
+ * Without this reset `touchApplied` stays `true` and every REAL mouse `mouseup` is routed into
581
+ * the touch tap detector, which has no button filter, so two right-clicks or two drag-selections
582
+ * ending on the same cell within the double-tap window would fire a phantom double-click.
583
+ * It also releases the mouse-down flag: a long-press fires `onMouseDown` from its timer, and
584
+ * after a cancel no `mouseup` ever follows, which would leave mouse-move selection dragging
585
+ * armed until the next click. The pending synthesized-pair flag is cleared for the same reason
586
+ * the scroll branch of `onTouchEnd` clears it: a cancelled gesture armed nothing, so a
587
+ * still-pending flag belongs to an earlier gesture whose pair never came, and left in place it
588
+ * would drop the next real mouse pair inside the ceiling on engines that do not report the
589
+ * input origin.
590
+ *
591
+ * @private
592
+ */ onTouchCancel() {
593
+ _class_private_method_get(this, _cancelLongPressTimer, cancelLongPressTimer).call(this);
594
+ this.touchApplied = false;
595
+ _class_private_field_set(this, _mouseDown, false);
596
+ _class_private_field_set(this, _touchWasMoved, false);
597
+ _class_private_field_set(this, _longPressFired, false);
598
+ _class_private_field_set(this, _deferredTouchStartEvent, null);
599
+ _class_private_field_set(this, _lastTapCoords, null);
600
+ _class_private_field_set(this, _synthesizedPairPending, false);
601
+ }
602
+ /**
494
603
  * Holder `scroll` callback. Cancels the long-press timer and runs the momentum-scroll
495
604
  * bookkeeping. When called during an active touch sequence it also marks the gesture
496
605
  * as a scroll so the deferred mousedown is not fired on `touchend` - native scrolling
@@ -574,7 +683,10 @@ var /**
574
683
  * @param {EventDeps} deps The Event module dependencies.
575
684
  * @param {Event} [parent=null] The main Event instance.
576
685
  */ constructor(deps, parent = null){
686
+ _class_private_method_init(this, _isTouchSynthesizedMouseEvent);
577
687
  _class_private_method_init(this, _getCellCoordsFromMousePosition);
688
+ _class_private_method_init(this, _handleTouchTap);
689
+ _class_private_method_init(this, _fireDblClick);
578
690
  _class_private_method_init(this, _startLongPressTimer);
579
691
  _class_private_method_init(this, _cancelLongPressTimer);
580
692
  _class_private_field_init(this, _deps, {
@@ -597,6 +709,14 @@ var /**
597
709
  writable: true,
598
710
  value: void 0
599
711
  });
712
+ _class_private_field_init(this, _lastTapCoords, {
713
+ writable: true,
714
+ value: void 0
715
+ });
716
+ _class_private_field_init(this, _lastTapAt, {
717
+ writable: true,
718
+ value: void 0
719
+ });
600
720
  _class_private_field_init(this, _longPressTimeout, {
601
721
  writable: true,
602
722
  value: void 0
@@ -621,6 +741,10 @@ var /**
621
741
  writable: true,
622
742
  value: void 0
623
743
  });
744
+ _class_private_field_init(this, _synthesizedPairPending, {
745
+ writable: true,
746
+ value: void 0
747
+ });
624
748
  _class_private_field_init(this, _mouseDown, {
625
749
  writable: true,
626
750
  value: void 0
@@ -638,12 +762,15 @@ var /**
638
762
  null,
639
763
  null
640
764
  ]);
765
+ _class_private_field_set(this, _lastTapCoords, null);
766
+ _class_private_field_set(this, _lastTapAt, 0);
641
767
  _class_private_field_set(this, _longPressTimeout, null);
642
768
  _class_private_field_set(this, _longPressFired, false);
643
769
  _class_private_field_set(this, _touchStartCoords, null);
644
770
  _class_private_field_set(this, _touchWasMoved, false);
645
771
  _class_private_field_set(this, _deferredTouchStartEvent, null);
646
772
  _class_private_field_set(this, _lastTouchMouseUpAt, 0);
773
+ _class_private_field_set(this, _synthesizedPairPending, false);
647
774
  _class_private_field_set(this, _mouseDown, false);
648
775
  _class_private_field_set(this, _mouseOverOutsideLastCoords, null);
649
776
  _class_private_field_set(this, _deps, deps);
@@ -651,9 +778,48 @@ var /**
651
778
  this.registerEvents();
652
779
  }
653
780
  }
781
+ function isTouchSynthesizedMouseEvent(event) {
782
+ if (getMouseEventTouchOrigin(event) === false) {
783
+ return false;
784
+ }
785
+ const withinCeiling = Date.now() - _class_private_field_get(this, _lastTouchMouseUpAt) < TOUCH_SYNTHESIZED_MOUSE_WINDOW;
786
+ if (!_class_private_field_get(this, _synthesizedPairPending) || !withinCeiling) {
787
+ _class_private_field_set(this, _synthesizedPairPending, false);
788
+ return false;
789
+ }
790
+ if (event.type === 'mouseup') {
791
+ _class_private_field_set(this, _synthesizedPairPending, false);
792
+ }
793
+ return true;
794
+ }
654
795
  function getCellCoordsFromMousePosition1(mouseX, mouseY) {
655
796
  return getCellCoordsFromMousePosition(_class_private_field_get(this, _deps), mouseX, mouseY);
656
797
  }
798
+ function handleTouchTap(event, cell) {
799
+ if (_class_private_field_get(this, _longPressFired) || !cell.TD || !cell.coords) {
800
+ _class_private_field_set(this, _lastTapCoords, null);
801
+ return;
802
+ }
803
+ const now = Date.now();
804
+ const isSameCell = _class_private_field_get(this, _lastTapCoords) !== null && _class_private_field_get(this, _lastTapCoords).row === cell.coords.row && _class_private_field_get(this, _lastTapCoords).col === cell.coords.col;
805
+ if (isSameCell && now - _class_private_field_get(this, _lastTapAt) < TOUCH_DBLTAP_TIMEOUT) {
806
+ _class_private_method_get(this, _fireDblClick, fireDblClick).call(this, event, cell);
807
+ _class_private_field_set(this, _lastTapCoords, null);
808
+ return;
809
+ }
810
+ // Clone: parentCell()'s border branches return references into the live selection CellRange,
811
+ // which normalize() mutates in place — a stored alias could silently shift within the
812
+ // double-tap window.
813
+ _class_private_field_set(this, _lastTapCoords, cell.coords.clone());
814
+ _class_private_field_set(this, _lastTapAt, now);
815
+ }
816
+ function fireDblClick(event, cell) {
817
+ if (hasClass(eventTargetEl(event), 'corner')) {
818
+ this.callListener('onCellCornerDblClick', event, cell.coords, cell.TD);
819
+ } else {
820
+ this.callListener('onCellDblClick', event, cell.coords, cell.TD);
821
+ }
822
+ }
657
823
  function startLongPressTimer(event) {
658
824
  _class_private_method_get(this, _cancelLongPressTimer, cancelLongPressTimer).call(this);
659
825
  const touch = event.touches[0];
@@ -674,6 +840,7 @@ function startLongPressTimer(event) {
674
840
  this.onMouseDown(event);
675
841
  _class_private_field_get(this, _dblClickOrigin)[0] = null;
676
842
  _class_private_field_get(this, _dblClickOrigin)[1] = null;
843
+ _class_private_field_set(this, _lastTapCoords, null);
677
844
  if (_class_private_field_get(this, _dblClickTimeout)[0] !== null) {
678
845
  clearTimeout(_class_private_field_get(this, _dblClickTimeout)[0]);
679
846
  }
package/CHANGELOG.md CHANGED
@@ -9,7 +9,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
10
  <!-- UNVERSIONED -->
11
11
 
12
- ## [18.1.0-rc7] - 2026-08-28
12
+ ## [18.1.0] - 2026-09-01
13
13
 
14
14
  ### Added
15
15
  - Added the `modifySinglePassLayout` hook, which forces the previous measure-then-render layout path for a table. [#12951](https://github.com/handsontable/handsontable/pull/12951)
@@ -50,6 +50,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
50
50
  - Improved the performance of bulk grid alterations: removing many rows or columns, inserting multiple columns, pasting data that extends the grid, and edits with the `minSpareCols` or `minCols` options on large datasets. [#13091](https://github.com/handsontable/handsontable/issues/13091)
51
51
  - Improved `getColHeader` performance: the index translation derived from the `columns` function is now cached instead of being rebuilt on every call, which also speeds up grid initialization and `updateSettings` on grids with many columns. [#13096](https://github.com/handsontable/handsontable/issues/13096)
52
52
  - Improved sizing plugins performance: AutoColumnSize measures only the changed cells on edits instead of rescanning whole columns, its background width sweep is budgeted and runs on browser idle time, AutoRowSize reuses the cached header height on selection-driven renders, and a multi-column resize triggers one height recalculation instead of one per column. [#13097](https://github.com/handsontable/handsontable/issues/13097)
53
+ - Changed how touch opens the cell editor on devices that report both touch and mouse input, such as iPad: a double-tap opens it (taps up to 1 second apart), and a single tap on an already selected cell no longer opens it as it did in 18.0.0, where duplicated mouse events after the tap triggered the double-click. [#13306](https://github.com/handsontable/handsontable/pull/13306)
53
54
 
54
55
  ### Removed
55
56
  - Removed leftover Pikaday styles from the themes. [#13156](https://github.com/handsontable/handsontable/pull/13156)
@@ -122,6 +123,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
122
123
  - Angular: Fixed custom editor shortcut groups in the Angular wrapper. [#13160](https://github.com/handsontable/handsontable/pull/13160)
123
124
  - Fixed the grid no longer responding to keyboard shortcuts after clicking focusable plugin UI placed in the grid's layout slots (for example, pagination controls). [#13243](https://github.com/handsontable/handsontable/pull/13243)
124
125
  - Fixed an open cell editor staying visible over an unrelated row, and committing to a row you could no longer see, when the edited cell was hidden - for example by turning a Pagination page or hiding its row or column. [#13245](https://github.com/handsontable/handsontable/pull/13245)
126
+ - Fixed an expired trial license key not blocking the grid when the key carried the `no-ui-warns` flag. [#13312](https://github.com/handsontable/handsontable/pull/13312)
125
127
 
126
128
  ### Security
127
129
  - Fixed pasted HTML being able to run scripts, and applied the `sanitizer` option to the surfaces that previously skipped it. [#13236](https://github.com/handsontable/handsontable/pull/13236)
@@ -148,7 +150,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
148
150
  - Included Walkontable in the main tsconfig.json type-check program and reduced as unknown escape-hatch casts in Walkontable from 68 to 10 (-85%) by using generics, union types, and direct structural assignments. [#12734](https://github.com/handsontable/handsontable/issues/12734)
149
151
  - Added typing for the `handsontable` cell type configuration and the `getValue` setting. [#12763](https://github.com/handsontable/handsontable/issues/12763)
150
152
  - Changed the Notification plugin to render its toasts in the grid's overlay layer. [#12777](https://github.com/handsontable/handsontable/issues/12777)
151
- - Angular: Modernized the Angular wrapper to align with Angular 17–19, simplify setup, reduce dependencies, and clean up tooling. [#12451](https://github.com/handsontable/handsontable/issues/12451)
152
153
  - Angular: Added support for installing Angular 16 through 22, without the --force flag [#12752](https://github.com/handsontable/handsontable/issues/12752)
153
154
  - Reduced memory usage and improved initialization time for large datasets by no longer materializing cell metadata for every cell during source data validation. [#12847](https://github.com/handsontable/handsontable/pull/12847)
154
155
 
@@ -182,7 +183,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
182
183
  - Fixed the dropdown/autocomplete editor overflowing the table's right boundary when `trimDropdown` is set to `false`. [#12506](https://github.com/handsontable/handsontable/issues/12506)
183
184
  - Fixed merged cells not following their data when columns or rows are reordered with `manualColumnMove`, `manualRowMove`, or `manualColumnFreeze`. Merges now translate with the underlying data; merges whose physical span becomes non-contiguous after a reorder auto-split into smaller merges, and any single-cell fragment left behind is dropped. [#12508](https://github.com/handsontable/handsontable/issues/12508)
184
185
  - Fixed the `handsontable` cell type editor closing unexpectedly when using filters or dropdown menu on the inner Handsontable instance. [#12510](https://github.com/handsontable/handsontable/issues/12510)
185
- - Fixed the loading overlay resetting the grid scroll position to the top when no cell was selected before showing the overlay. [#12514](https://github.com/handsontable/handsontable/issues/12514)
186
186
  - Fixed manual column and row resize handle position after scrolling when `preventOverflow` is set. [#12515](https://github.com/handsontable/handsontable/issues/12515)
187
187
  - Fixed the table visually overflowing the configured `width` when `height` was not set. [#12517](https://github.com/handsontable/handsontable/pull/12517)
188
188
  - Fixed Prevent crash when Handsontable is initialized inside a hidden container, rowsRenderCalculator and columnsRenderCalculator on Viewport are never assigned and remain undefined. [#12533](https://github.com/handsontable/handsontable/issues/12533)
@@ -195,14 +195,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
195
195
  - Fixed custom editor object values with a different schema being silently discarded by populateFromArray. [#12562](https://github.com/handsontable/handsontable/issues/12562)
196
196
  - Fixed `beforeColumnResize` and `beforeRowResize` hook return values being ignored during drag resize. [#12566](https://github.com/handsontable/handsontable/issues/12566)
197
197
  - Fixed formulas not being evaluated for array-of-arrays datasets when the `columns` option skips physical column indexes. [#12569](https://github.com/handsontable/handsontable/issues/12569)
198
- - Fixed a memory leak caused by ThemeManager not unsubscribing from the shared theme object on destroy. [#12570](https://github.com/handsontable/handsontable/issues/12570)
199
- - Fixed viewport scroll jump when Ctrl+clicking a selected cell to deselect it. [#12574](https://github.com/handsontable/handsontable/issues/12574)
200
- - Fixed a memory leak where IntersectionObserver instances were not properly disconnected when `document.body` had zero height. [#12578](https://github.com/handsontable/handsontable/issues/12578)
201
198
  - Fixed a crash when calling `setSourceDataAtCell()` inside the `afterLoadData()` hook during initialization. [#12585](https://github.com/handsontable/handsontable/issues/12585)
202
199
  - Fixed context menu items in object form (e.g. `add_child`, `detach_from_parent`) not rendering plugin-provided callbacks and translated labels. [#12586](https://github.com/handsontable/handsontable/issues/12586)
203
200
  - Fixed page scroll jump when inserting or removing a row/column near the bottom of the page on a grid with no fixed height. [#12587](https://github.com/handsontable/handsontable/issues/12587)
204
201
  - Fixed NestedRows context menu "Insert row above/below" destroying sibling branches on a deeply-nested leaf. [#12590](https://github.com/handsontable/handsontable/issues/12590)
205
- - Fixed the browser page scrolling to the grid when `dataProvider` loads rows for the first time into an empty grid with `emptyDataState` enabled. [#12591](https://github.com/handsontable/handsontable/issues/12591)
206
202
  - Fixed a crash when `updateSettings` was called from the `beforeContextMenuShow` or `beforeDropdownMenuShow` hook. [#12593](https://github.com/handsontable/handsontable/issues/12593)
207
203
  - Fixed the comment editor rendering off-screen on narrow viewports such as mobile portrait. [#12594](https://github.com/handsontable/handsontable/issues/12594)
208
204
  - Fixed nested headers rendering incorrectly when manualColumnMove and hiddenColumns are combined. [#12610](https://github.com/handsontable/handsontable/issues/12610)
@@ -252,9 +248,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
252
248
  - Added build weight comparison tables to the Modules guide, showing the minified and gzip size added by each optional module when imported on top of `handsontable/base`. [#12262](https://github.com/handsontable/handsontable/issues/12262)
253
249
  - Added Notification plugin for non-blocking toast notifications. [#12299](https://github.com/handsontable/handsontable/issues/12299)
254
250
  - Added long-press gesture detection on touch devices to open the context menu. [#12306](https://github.com/handsontable/handsontable/issues/12306)
255
- - Added dedicated `paginationButton*` theme tokens so pagination navigation button colors can be customized independently via the theme builder. [#12317](https://github.com/handsontable/handsontable/issues/12317)
256
- - Added dedicated `paginationButton*` theme tokens so pagination navigation button colors can be customized independently for default, hover, focus, and disabled states via the theme builder. [#12404](https://github.com/handsontable/handsontable/issues/12404)
257
- - Added `rowspan` support to the NestedHeaders plugin, allowing column headers to span multiple header rows. [#191](https://github.com/handsontable/handsontable/issues/191)
251
+ - Added dedicated `paginationButton*` theme tokens so pagination navigation button colors can be customized independently for default, hover, focus, and disabled states via the theme builder. [#12404](https://github.com/handsontable/handsontable/issues/12404) [#12317](https://github.com/handsontable/handsontable/issues/12317)
258
252
 
259
253
  ### Changed
260
254
  - Added a frame-based e2e test wait helper and replaced selected hook test sleeps. [#12161](https://github.com/handsontable/handsontable/pull/12161)
@@ -266,7 +260,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
266
260
  ### Fixed
267
261
  - Fixed an issue where the Nested Rows plugin was disabled after calling updateSettings with an empty data array. [#10556](https://github.com/handsontable/handsontable/issues/10556)
268
262
  - Fixed `setSourceDataAtCell()` updating parent rows instead of nested child rows when `nestedRows` is enabled. [#10657](https://github.com/handsontable/handsontable/issues/10657)
269
- - Fixed an issue where the stretchH: 'last' option would ignore the defined column width when the viewport was too narrow, causing the last column to shrink to 0px. [#11761](https://github.com/handsontable/handsontable/issues/11761)
270
263
  - Fixed a stack overflow error when pasting large datasets (50,000+ rows) by optimizing array operations in the HTML table parser. [#11784](https://github.com/handsontable/handsontable/issues/11784)
271
264
  - Fixed incorrect JSDoc type annotations for the `modifyAutofillRange` hook parameters. The parameters `entireArea` and `startArea` are now correctly documented as `number[]` (a flat 4-element array) instead of the generic `Array` type, and the `@returns` type annotation has been added. [#11862](https://github.com/handsontable/handsontable/issues/11862)
272
265
  - Fixed filter by value input performance degradation when searchMode: apply option is enabled. [#12104](https://github.com/handsontable/handsontable/issues/12104)
@@ -278,7 +271,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
278
271
  - Fixed column resizing being misaligned and calculating incorrect widths when the grid container has a CSS `transform: scale()` applied. [#11838](https://github.com/handsontable/handsontable/issues/11838)
279
272
  - Fixed the `stretchH: 'last'` option ignoring the defined column width and shrinking the last column to 0px when the viewport was too narrow. [#11761](https://github.com/handsontable/handsontable/issues/11761)
280
273
  - Fixed HyperFormula errors when MultiSelect cells store array values. [#12135](https://github.com/handsontable/handsontable/pull/12135)
281
- - Fixed `setSourceDataAtCell()` updating a parent row instead of the intended nested child row when the `nestedRows` option was enabled. [#10657](https://github.com/handsontable/handsontable/issues/10657)
282
274
  - Fixed `setDataAtRowProp()` incorrectly canceling an active editor session when the programmatic update targeted a different cell in the same row. [#4305](https://github.com/handsontable/handsontable/issues/4305)
283
275
  - Fix ThemeBuilder false unknown token warning on initialization [#12146](https://github.com/handsontable/handsontable/pull/12146)
284
276
  - Prevent after scroll hooks from firing when axis position is unchanged [#12151](https://github.com/handsontable/handsontable/issues/12151)
@@ -294,9 +286,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
294
286
  - Fixed framework wrappers crashing when init-only settings (renderAllRows, renderAllColumns, layoutDirection, ariaTags) changed after initialization. [#12242](https://github.com/handsontable/handsontable/issues/12242)
295
287
  - Fixed an issue where `currentRowClassName` and `currentColClassName` could not be changed dynamically using `updateSettings`. [#12247](https://github.com/handsontable/handsontable/issues/12247)
296
288
  - Fixed column menu dropdown button styling when a filtered column header is also active [#12253](https://github.com/handsontable/handsontable/issues/12253)
297
- - Fixed an issue where rows with dataSchema default values (e.g., false for checkbox columns) were not recognized as empty by isEmptyRow and isEmptyCol, causing minSpareRows and minSpareCols to add infinite rows. [#12254](https://github.com/handsontable/handsontable/issues/12254)
289
+ - Fixed an issue where rows with dataSchema default values (e.g., false for checkbox columns) were not recognized as empty by isEmptyRow and isEmptyCol, causing minSpareRows and minSpareCols to add infinite rows. [#12254](https://github.com/handsontable/handsontable/issues/12254) [#2409](https://github.com/handsontable/handsontable/issues/2409)
298
290
  - Fixed autocomplete editor with strict mode and allowInvalid discarding typed value on click-away instead of saving it. [#12285](https://github.com/handsontable/handsontable/issues/12285)
299
- - Fixed incorrect JSDoc type annotations for the `modifyAutofillRange` hook's `entireArea` and `startArea` parameters, and added the missing `@returns` annotation. [#11862](https://github.com/handsontable/handsontable/issues/11862)
300
291
  - Fixed filter-by-value search by trimming leading and trailing spaces and treating whitespace-only input as an empty query. [#12290](https://github.com/handsontable/handsontable/issues/12290)
301
292
  - Fixed portal-based popups (e.g., date picker) closing immediately on touch devices (Android) due to outside-click detection not accounting for rootPortalElement. [#12298](https://github.com/handsontable/handsontable/pull/12298)
302
293
  - Fixed `setDataAtRowProp` ignoring the `source` parameter in array-form calls, causing `beforeChange` and `afterChange` hooks to always receive `'edit'` instead of the provided source string. [#12300](https://github.com/handsontable/handsontable/issues/12300)
@@ -307,9 +298,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
307
298
  - Fixed the `headerRowBackgroundColor` theme token having no visual effect on row headers. The `rowHeaderOddBackgroundColor` and `rowHeaderEvenBackgroundColor` tokens now derive from `headerRowBackgroundColor` by default, so customizing it properly cascades to all row headers. [#12322](https://github.com/handsontable/handsontable/issues/12322)
308
299
  - Fixed an exception when showing the loading indicator from the `afterChange` hook during editor close. [#12348](https://github.com/handsontable/handsontable/issues/12348)
309
300
  - Fixed TypeScript type for the `dateFormat` option to accept `Intl.DateTimeFormatOptions` objects required by the `intl-date` cell type. [#12395](https://github.com/handsontable/handsontable/issues/12395)
310
- - Fixed an issue where minSpareRows and minSpareCols kept adding rows/columns when dataSchema defined non-null default values (e.g. false for checkbox columns). [#2409](https://github.com/handsontable/handsontable/issues/2409)
311
- - Fixed one-pixel horizontal alignment for the left pagination caret [#2791](https://github.com/handsontable/handsontable/pull/2791)
312
- - Fixed setDataAtRowProp interrupting edits in progress [#4305](https://github.com/handsontable/handsontable/issues/4305)
313
301
  - React: Fixed the React wrapper skipping settings updates when `dataSchema` or `columns` contains non-plain objects such as `Date`, `Set`, or `Map`. [#12207](https://github.com/handsontable/handsontable/pull/12207)
314
302
  - Fixed the loading overlay resetting the grid scroll position to the top when no cell was selected before showing the overlay. [#12514](https://github.com/handsontable/handsontable/issues/12514)
315
303
  - Fixed a memory leak caused by ThemeManager not unsubscribing from the shared theme object on destroy. [#12570](https://github.com/handsontable/handsontable/issues/12570)
@@ -353,7 +341,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
353
341
 
354
342
  ### Changed
355
343
  - Improved differentiation between Handsontable errors and other errors. [#11780](https://github.com/handsontable/handsontable/pull/11780)
356
- - Reverted the editors' `updateChoicesList` method type change. [#11943](https://github.com/handsontable/handsontable/pull/11943)
357
344
  - Added a hit area to the fill handle. [#11952](https://github.com/handsontable/handsontable/pull/11952)
358
345
  - Added a new `parsePastedValue` option to fix issues with pasting object-based values. [#12020](https://github.com/handsontable/handsontable/pull/12020)
359
346
  - Introduced a new publishing flow for versions 17.0.0 and above. [#12028](https://github.com/handsontable/handsontable/pull/12028)
@@ -454,7 +441,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
454
441
  - Fixed incorrect resizing behavior when auto-sizing rows or columns by double-clicking separators. [#11671](https://github.com/handsontable/handsontable/pull/11671)
455
442
  - Fixed mouse wheel zooming issues on Windows. [#11680](https://github.com/handsontable/handsontable/pull/11680)
456
443
  - Fixed autocomplete sorting and option highlighting issues. [#11708](https://github.com/handsontable/handsontable/pull/11708)
457
- - Fixed a missing `touchend` handler that prevented editors from opening on mobile devices. [#11729](https://github.com/handsontable/handsontable/pull/11729)
458
444
  - Fixed misalignment between rows and row headers when using `autoRowSize`. [#11736](https://github.com/handsontable/handsontable/pull/11736)
459
445
  - Fixed layout inconsistencies caused by browser zoom and scaling. [#11739](https://github.com/handsontable/handsontable/pull/11739)
460
446
  - Fixed an issue with the root-wrapper height calculation. [#11769](https://github.com/handsontable/handsontable/pull/11769)
@@ -636,7 +622,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
636
622
  - Fixed a problem with the header widths when using Nested Headers with the new themes enabled. [#11410](https://github.com/handsontable/handsontable/pull/11410)
637
623
  - Fixed the header text overlap in Nested Headers. [#11413](https://github.com/handsontable/handsontable/pull/11413)
638
624
  - Fixed a problem with the merged cells height calculation in the new themes. [#11423](https://github.com/handsontable/handsontable/pull/11423)
639
- - Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
640
625
  - Fixed a problem, where clicking on the Comments' editor element deselected the currently selected cells. [#11446](https://github.com/handsontable/handsontable/pull/11446)
641
626
 
642
627
  ## [15.0.1] - 2025-02-10
@@ -644,16 +629,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
644
629
  ### Fixed
645
630
  - Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
646
631
 
647
- ## [14.6.2] - 2025-02-10
648
-
649
- ### Fixed
650
- - Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
651
-
652
632
  ## [15.0.0] - 2024-12-16
653
633
 
654
634
  ### Added
655
635
  - Added support for row and column virtualization of merged cells. [#11162](https://github.com/handsontable/handsontable/pull/11162)
656
636
  - Added missing typings for the language files. [#11236](https://github.com/handsontable/handsontable/pull/11236)
637
+ - Added support for the new themes, including "main" and "horizon". [#11144](https://github.com/handsontable/handsontable/pull/11144)
657
638
  - React: Added `@handsontable/react-wrapper` to the monorepo. [#11212](https://github.com/handsontable/handsontable/pull/11212)
658
639
 
659
640
  ### Changed
@@ -664,7 +645,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
664
645
 
665
646
  ### Removed
666
647
  - **Breaking change**: Removed check marks from the Context Menu's alignment submenu. [#11278](https://github.com/handsontable/handsontable/pull/11278)
667
- - Removed `aria-hidden` from TextEditor's and PasswordEditor's `TEXTAREA` elements. [#11218](https://github.com/handsontable/handsontable/pull/11218)
668
648
 
669
649
  ### Fixed
670
650
  - Fixed the Autocomplete and Dropdown editors' container size calculations. [#11201](https://github.com/handsontable/handsontable/pull/11201)
@@ -687,7 +667,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
687
667
 
688
668
  ## [14.6.2] - 2025-02-10
689
669
 
690
- #### Fixed
670
+ ### Fixed
691
671
  - Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
692
672
 
693
673
  ## [14.6.1] - 2024-10-17
@@ -737,10 +717,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
737
717
  - Improved the rendering performance. [#11069](https://github.com/handsontable/handsontable/pull/11069)
738
718
 
739
719
  ### Fixed
740
- - Fixed Context.getShortcuts type. [#10910](https://github.com/handsontable/handsontable/pull/10910)
741
720
  - Improved performance of cell merging. [#10995](https://github.com/handsontable/handsontable/pull/10995)
742
721
  - Fixed a problem where clicking and dragging on cells in window-controlled scrolled instances would result in unpredictable behavior. [#10996](https://github.com/handsontable/handsontable/pull/10996)
743
- - Fixed a bug that prevented column sorting of the checkbox cell types. [#11004](https://github.com/handsontable/handsontable/pull/11004)
744
722
  - Fixed merged cells misalignment in overlays. [#11007](https://github.com/handsontable/handsontable/pull/11007)
745
723
  - Fixed selection expansion for merged cells. [#11010](https://github.com/handsontable/handsontable/pull/11010)
746
724
  - Fixed a problem where the table could go into an endless resize loop when one of the instance's parents was using `dvh` values for sizing, and the table was not given any size itself. [#11021](https://github.com/handsontable/handsontable/pull/11021)
@@ -951,7 +929,6 @@ For more information on Handsontable 14.1.0, see:
951
929
  - **Breaking change**: Changed the way Handsontable handles focus by focusing the browser on cell elements. Introduced a new `imeFastEdit` option to minimize the negative effects affecting the "fast edit" feature for the IME users. [#10342](https://github.com/handsontable/handsontable/pull/10342)
952
930
  - Extended the Core's `scrollViewportTo` method to allow disabling of cell auto-snapping. [#10508](https://github.com/handsontable/handsontable/pull/10508)
953
931
  - Improved the keyboard navigation for the context and dropdown menus and added a new `forwardToContext` option to the ShortcutManager. [#10519](https://github.com/handsontable/handsontable/pull/10519)
954
- - Upgraded the monorepo to utilize Node 20. [#10468](https://github.com/handsontable/handsontable/pull/10468)
955
932
  - Improved DX by adding an exception to be thrown when trying to activate a shortcut context that has been not yet registered. [#10476](https://github.com/handsontable/handsontable/pull/10476)
956
933
  - Improved the performance of the table for cases when the table is hidden. [#10490](https://github.com/handsontable/handsontable/pull/10490)
957
934
  - Updated the TS definitions for the HiddenRows and HiddenColumns plugins. [#10492](https://github.com/handsontable/handsontable/pull/10492)
package/base.js CHANGED
@@ -72,8 +72,8 @@ Handsontable.hooks = _hooks.Hooks.getSingleton();
72
72
  Handsontable.CellCoords = _src.CellCoords;
73
73
  Handsontable.CellRange = _src.CellRange;
74
74
  Handsontable.packageName = 'handsontable';
75
- Handsontable.buildDate = "28/08/2026 09:08:22";
76
- Handsontable.version = "18.1.0-rc8";
75
+ Handsontable.buildDate = "01/09/2026 11:40:24";
76
+ Handsontable.version = "18.1.0";
77
77
  Handsontable.languages = {
78
78
  dictionaryKeys: _registry.dictionaryKeys,
79
79
  getLanguageDictionary: _registry.getLanguageDictionary,
package/base.mjs CHANGED
@@ -43,8 +43,8 @@ Handsontable.hooks = Hooks.getSingleton();
43
43
  Handsontable.CellCoords = CellCoords;
44
44
  Handsontable.CellRange = CellRange;
45
45
  Handsontable.packageName = 'handsontable';
46
- Handsontable.buildDate = "28/08/2026 09:08:22";
47
- Handsontable.version = "18.1.0-rc8";
46
+ Handsontable.buildDate = "01/09/2026 11:40:24";
47
+ Handsontable.version = "18.1.0";
48
48
  Handsontable.languages = {
49
49
  dictionaryKeys,
50
50
  getLanguageDictionary,