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.
- package/3rdparty/walkontable/src/event.d.ts +17 -0
- package/3rdparty/walkontable/src/event.js +188 -21
- package/3rdparty/walkontable/src/event.mjs +188 -21
- package/CHANGELOG.md +7 -30
- package/base.js +2 -2
- package/base.mjs +2 -2
- package/dist/handsontable.full.js +2263 -2011
- package/dist/handsontable.full.min.js +117 -117
- package/dist/handsontable.js +2262 -2011
- package/dist/handsontable.min.js +117 -117
- package/dist/themes/classic.js +2 -2
- package/dist/themes/classic.min.js +2 -2
- package/dist/themes/horizon.js +2 -2
- package/dist/themes/horizon.min.js +2 -2
- package/dist/themes/main.js +2 -2
- package/dist/themes/main.min.js +2 -2
- package/dist/themes/static/variables/colors/ant.js +2 -2
- package/dist/themes/static/variables/colors/ant.min.js +2 -2
- package/dist/themes/static/variables/colors/classic.js +2 -2
- package/dist/themes/static/variables/colors/classic.min.js +2 -2
- package/dist/themes/static/variables/colors/horizon.js +2 -2
- package/dist/themes/static/variables/colors/horizon.min.js +2 -2
- package/dist/themes/static/variables/colors/main.js +2 -2
- package/dist/themes/static/variables/colors/main.min.js +2 -2
- package/dist/themes/static/variables/colors/material.js +2 -2
- package/dist/themes/static/variables/colors/material.min.js +2 -2
- package/dist/themes/static/variables/colors/shadcn.js +2 -2
- package/dist/themes/static/variables/colors/shadcn.min.js +2 -2
- package/dist/themes/static/variables/density.js +2 -2
- package/dist/themes/static/variables/density.min.js +2 -2
- package/dist/themes/static/variables/helpers/iconsMap.js +2 -2
- package/dist/themes/static/variables/helpers/iconsMap.min.js +2 -2
- package/dist/themes/static/variables/icons/horizon.js +2 -2
- package/dist/themes/static/variables/icons/horizon.min.js +2 -2
- package/dist/themes/static/variables/icons/main.js +2 -2
- package/dist/themes/static/variables/icons/main.min.js +2 -2
- package/dist/themes/static/variables/sizing.js +2 -2
- package/dist/themes/static/variables/sizing.min.js +2 -2
- package/dist/themes/static/variables/tokens/classic.js +2 -2
- package/dist/themes/static/variables/tokens/classic.min.js +2 -2
- package/dist/themes/static/variables/tokens/horizon.js +2 -2
- package/dist/themes/static/variables/tokens/horizon.min.js +2 -2
- package/dist/themes/static/variables/tokens/main.js +2 -2
- package/dist/themes/static/variables/tokens/main.min.js +2 -2
- package/helpers/dom/inputOrigin.d.mts +1 -0
- package/helpers/dom/inputOrigin.d.ts +38 -0
- package/helpers/dom/inputOrigin.js +54 -0
- package/helpers/dom/inputOrigin.mjs +48 -0
- package/helpers/mixed.js +20 -5
- package/helpers/mixed.mjs +20 -5
- package/package.json +1 -1
- package/styles/handsontable.css +2 -2
- package/styles/handsontable.min.css +2 -2
- package/styles/handsontableStyles.js +1 -1
- package/styles/handsontableStyles.mjs +1 -1
- package/styles/ht-icons-horizon.min.css +2 -2
- package/styles/ht-icons-main.min.css +2 -2
- package/styles/ht-theme-classic-no-icons.min.css +2 -2
- package/styles/ht-theme-classic.min.css +2 -2
- package/styles/ht-theme-horizon-no-icons.min.css +2 -2
- package/styles/ht-theme-horizon.min.css +2 -2
- package/styles/ht-theme-main-no-icons.min.css +2 -2
- package/styles/ht-theme-main.min.css +2 -2
- package/tableView.js +16 -12
- package/tableView.mjs +16 -12
- package/utils/entitlementLicenseKey/constants.d.ts +9 -3
- package/utils/entitlementLicenseKey/constants.mjs +9 -3
- package/utils/entitlementLicenseKey/types.d.ts +9 -3
- package/utils/licenseBranding/index.js +22 -7
- package/utils/licenseBranding/index.mjs +22 -7
- package/utils/licenseNotification.js +2 -2
- package/utils/licenseNotification.mjs +2 -2
- package/styles/handsontableStyles.d.mts +0 -2
- 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
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
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
|
-
|
|
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)=>
|
|
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
|
-
//
|
|
281
|
-
|
|
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
|
-
},
|
|
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
|
-
|
|
398
|
-
|
|
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
|
-
|
|
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
|
-
},
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 = "
|
|
76
|
-
Handsontable.version = "18.1.0
|
|
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 = "
|
|
47
|
-
Handsontable.version = "18.1.0
|
|
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,
|