handsontable 18.1.0-rc7 → 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 +12 -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)
|
|
@@ -21,6 +21,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
21
21
|
- Added the `colorScheme` and `density` options, which set the color scheme and the spacing of the grid without declaring a theme. [#13205](https://github.com/handsontable/handsontable/pull/13205)
|
|
22
22
|
- Added a public API to the `NestedRows` plugin for collapsing and expanding parent rows: `collapseAll()`, `expandAll()`, `collapseParent()`, `expandParent()`, `toggleParent()`, `getCollapsedParents()`, `isParentCollapsed()`, `isParent()`, `getRowLevel()`, `getRowParent()`, `countChildren()`, `expandToRow()`, and `expandToLevel()`, plus the new `beforeRowCollapse`, `afterRowCollapse`, `beforeRowExpand`, and `afterRowExpand` hooks. The plugin also no longer loses its collapsed rows on an `updateSettings()` call, and no longer throws when asked for the index, parent, or nesting level of a row object held from before a `loadData()` or `updateData()` call. [#13206](https://github.com/handsontable/handsontable/pull/13206)
|
|
23
23
|
- Added the `formulas.hyperlinks` option, which renders cells holding a `HYPERLINK` formula as clickable links. [#13223](https://github.com/handsontable/handsontable/pull/13223)
|
|
24
|
+
- Added the `SanitizerContext` type, which lists the write surfaces the `sanitizer` option receives. [#13240](https://github.com/handsontable/handsontable/pull/13240)
|
|
24
25
|
|
|
25
26
|
### Changed
|
|
26
27
|
- Reduced memory usage when scrolling large datasets by releasing cell metadata for rows scrolled out of the viewport. [#12854](https://github.com/handsontable/handsontable/pull/12854)
|
|
@@ -49,6 +50,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
49
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)
|
|
50
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)
|
|
51
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)
|
|
52
54
|
|
|
53
55
|
### Removed
|
|
54
56
|
- Removed leftover Pikaday styles from the themes. [#13156](https://github.com/handsontable/handsontable/pull/13156)
|
|
@@ -121,6 +123,11 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
121
123
|
- Angular: Fixed custom editor shortcut groups in the Angular wrapper. [#13160](https://github.com/handsontable/handsontable/pull/13160)
|
|
122
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)
|
|
123
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)
|
|
127
|
+
|
|
128
|
+
### Security
|
|
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)
|
|
130
|
+
- Fixed the `dialog` plugin interpolating an unvalidated `template.id` into the dialog's `id` attribute, and the `loading` plugin rendering its `title` and `description` options as HTML. Those two `loading` options now render as text, so markup passed in them shows up literally instead of being interpreted; use `icon` for markup. The button `type` option of the `dialog`, `emptyDataState`, and `notification` plugins is now resolved where the markup is built. [#13242](https://github.com/handsontable/handsontable/pull/13242)
|
|
124
131
|
|
|
125
132
|
## [18.0.0] - 2026-06-30
|
|
126
133
|
|
|
@@ -143,7 +150,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
143
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)
|
|
144
151
|
- Added typing for the `handsontable` cell type configuration and the `getValue` setting. [#12763](https://github.com/handsontable/handsontable/issues/12763)
|
|
145
152
|
- Changed the Notification plugin to render its toasts in the grid's overlay layer. [#12777](https://github.com/handsontable/handsontable/issues/12777)
|
|
146
|
-
- 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)
|
|
147
153
|
- Angular: Added support for installing Angular 16 through 22, without the --force flag [#12752](https://github.com/handsontable/handsontable/issues/12752)
|
|
148
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)
|
|
149
155
|
|
|
@@ -177,7 +183,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
177
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)
|
|
178
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)
|
|
179
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)
|
|
180
|
-
- 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)
|
|
181
186
|
- Fixed manual column and row resize handle position after scrolling when `preventOverflow` is set. [#12515](https://github.com/handsontable/handsontable/issues/12515)
|
|
182
187
|
- Fixed the table visually overflowing the configured `width` when `height` was not set. [#12517](https://github.com/handsontable/handsontable/pull/12517)
|
|
183
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)
|
|
@@ -190,14 +195,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
190
195
|
- Fixed custom editor object values with a different schema being silently discarded by populateFromArray. [#12562](https://github.com/handsontable/handsontable/issues/12562)
|
|
191
196
|
- Fixed `beforeColumnResize` and `beforeRowResize` hook return values being ignored during drag resize. [#12566](https://github.com/handsontable/handsontable/issues/12566)
|
|
192
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)
|
|
193
|
-
- Fixed a memory leak caused by ThemeManager not unsubscribing from the shared theme object on destroy. [#12570](https://github.com/handsontable/handsontable/issues/12570)
|
|
194
|
-
- Fixed viewport scroll jump when Ctrl+clicking a selected cell to deselect it. [#12574](https://github.com/handsontable/handsontable/issues/12574)
|
|
195
|
-
- 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)
|
|
196
198
|
- Fixed a crash when calling `setSourceDataAtCell()` inside the `afterLoadData()` hook during initialization. [#12585](https://github.com/handsontable/handsontable/issues/12585)
|
|
197
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)
|
|
198
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)
|
|
199
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)
|
|
200
|
-
- 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)
|
|
201
202
|
- Fixed a crash when `updateSettings` was called from the `beforeContextMenuShow` or `beforeDropdownMenuShow` hook. [#12593](https://github.com/handsontable/handsontable/issues/12593)
|
|
202
203
|
- Fixed the comment editor rendering off-screen on narrow viewports such as mobile portrait. [#12594](https://github.com/handsontable/handsontable/issues/12594)
|
|
203
204
|
- Fixed nested headers rendering incorrectly when manualColumnMove and hiddenColumns are combined. [#12610](https://github.com/handsontable/handsontable/issues/12610)
|
|
@@ -247,9 +248,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
247
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)
|
|
248
249
|
- Added Notification plugin for non-blocking toast notifications. [#12299](https://github.com/handsontable/handsontable/issues/12299)
|
|
249
250
|
- Added long-press gesture detection on touch devices to open the context menu. [#12306](https://github.com/handsontable/handsontable/issues/12306)
|
|
250
|
-
- 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)
|
|
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)
|
|
252
|
-
- 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)
|
|
253
252
|
|
|
254
253
|
### Changed
|
|
255
254
|
- Added a frame-based e2e test wait helper and replaced selected hook test sleeps. [#12161](https://github.com/handsontable/handsontable/pull/12161)
|
|
@@ -261,7 +260,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
261
260
|
### Fixed
|
|
262
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)
|
|
263
262
|
- Fixed `setSourceDataAtCell()` updating parent rows instead of nested child rows when `nestedRows` is enabled. [#10657](https://github.com/handsontable/handsontable/issues/10657)
|
|
264
|
-
- 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)
|
|
265
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)
|
|
266
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)
|
|
267
265
|
- Fixed filter by value input performance degradation when searchMode: apply option is enabled. [#12104](https://github.com/handsontable/handsontable/issues/12104)
|
|
@@ -273,7 +271,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
273
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)
|
|
274
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)
|
|
275
273
|
- Fixed HyperFormula errors when MultiSelect cells store array values. [#12135](https://github.com/handsontable/handsontable/pull/12135)
|
|
276
|
-
- 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)
|
|
277
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)
|
|
278
275
|
- Fix ThemeBuilder false unknown token warning on initialization [#12146](https://github.com/handsontable/handsontable/pull/12146)
|
|
279
276
|
- Prevent after scroll hooks from firing when axis position is unchanged [#12151](https://github.com/handsontable/handsontable/issues/12151)
|
|
@@ -289,9 +286,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
289
286
|
- Fixed framework wrappers crashing when init-only settings (renderAllRows, renderAllColumns, layoutDirection, ariaTags) changed after initialization. [#12242](https://github.com/handsontable/handsontable/issues/12242)
|
|
290
287
|
- Fixed an issue where `currentRowClassName` and `currentColClassName` could not be changed dynamically using `updateSettings`. [#12247](https://github.com/handsontable/handsontable/issues/12247)
|
|
291
288
|
- Fixed column menu dropdown button styling when a filtered column header is also active [#12253](https://github.com/handsontable/handsontable/issues/12253)
|
|
292
|
-
- 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)
|
|
293
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)
|
|
294
|
-
- 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)
|
|
295
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)
|
|
296
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)
|
|
297
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)
|
|
@@ -302,9 +298,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
302
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)
|
|
303
299
|
- Fixed an exception when showing the loading indicator from the `afterChange` hook during editor close. [#12348](https://github.com/handsontable/handsontable/issues/12348)
|
|
304
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)
|
|
305
|
-
- 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)
|
|
306
|
-
- Fixed one-pixel horizontal alignment for the left pagination caret [#2791](https://github.com/handsontable/handsontable/pull/2791)
|
|
307
|
-
- Fixed setDataAtRowProp interrupting edits in progress [#4305](https://github.com/handsontable/handsontable/issues/4305)
|
|
308
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)
|
|
309
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)
|
|
310
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)
|
|
@@ -348,7 +341,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
348
341
|
|
|
349
342
|
### Changed
|
|
350
343
|
- Improved differentiation between Handsontable errors and other errors. [#11780](https://github.com/handsontable/handsontable/pull/11780)
|
|
351
|
-
- Reverted the editors' `updateChoicesList` method type change. [#11943](https://github.com/handsontable/handsontable/pull/11943)
|
|
352
344
|
- Added a hit area to the fill handle. [#11952](https://github.com/handsontable/handsontable/pull/11952)
|
|
353
345
|
- Added a new `parsePastedValue` option to fix issues with pasting object-based values. [#12020](https://github.com/handsontable/handsontable/pull/12020)
|
|
354
346
|
- Introduced a new publishing flow for versions 17.0.0 and above. [#12028](https://github.com/handsontable/handsontable/pull/12028)
|
|
@@ -449,7 +441,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
449
441
|
- Fixed incorrect resizing behavior when auto-sizing rows or columns by double-clicking separators. [#11671](https://github.com/handsontable/handsontable/pull/11671)
|
|
450
442
|
- Fixed mouse wheel zooming issues on Windows. [#11680](https://github.com/handsontable/handsontable/pull/11680)
|
|
451
443
|
- Fixed autocomplete sorting and option highlighting issues. [#11708](https://github.com/handsontable/handsontable/pull/11708)
|
|
452
|
-
- Fixed a missing `touchend` handler that prevented editors from opening on mobile devices. [#11729](https://github.com/handsontable/handsontable/pull/11729)
|
|
453
444
|
- Fixed misalignment between rows and row headers when using `autoRowSize`. [#11736](https://github.com/handsontable/handsontable/pull/11736)
|
|
454
445
|
- Fixed layout inconsistencies caused by browser zoom and scaling. [#11739](https://github.com/handsontable/handsontable/pull/11739)
|
|
455
446
|
- Fixed an issue with the root-wrapper height calculation. [#11769](https://github.com/handsontable/handsontable/pull/11769)
|
|
@@ -631,7 +622,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
631
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)
|
|
632
623
|
- Fixed the header text overlap in Nested Headers. [#11413](https://github.com/handsontable/handsontable/pull/11413)
|
|
633
624
|
- Fixed a problem with the merged cells height calculation in the new themes. [#11423](https://github.com/handsontable/handsontable/pull/11423)
|
|
634
|
-
- Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
|
|
635
625
|
- Fixed a problem, where clicking on the Comments' editor element deselected the currently selected cells. [#11446](https://github.com/handsontable/handsontable/pull/11446)
|
|
636
626
|
|
|
637
627
|
## [15.0.1] - 2025-02-10
|
|
@@ -639,16 +629,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
639
629
|
### Fixed
|
|
640
630
|
- Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
|
|
641
631
|
|
|
642
|
-
## [14.6.2] - 2025-02-10
|
|
643
|
-
|
|
644
|
-
### Fixed
|
|
645
|
-
- Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
|
|
646
|
-
|
|
647
632
|
## [15.0.0] - 2024-12-16
|
|
648
633
|
|
|
649
634
|
### Added
|
|
650
635
|
- Added support for row and column virtualization of merged cells. [#11162](https://github.com/handsontable/handsontable/pull/11162)
|
|
651
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)
|
|
652
638
|
- React: Added `@handsontable/react-wrapper` to the monorepo. [#11212](https://github.com/handsontable/handsontable/pull/11212)
|
|
653
639
|
|
|
654
640
|
### Changed
|
|
@@ -659,7 +645,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
659
645
|
|
|
660
646
|
### Removed
|
|
661
647
|
- **Breaking change**: Removed check marks from the Context Menu's alignment submenu. [#11278](https://github.com/handsontable/handsontable/pull/11278)
|
|
662
|
-
- Removed `aria-hidden` from TextEditor's and PasswordEditor's `TEXTAREA` elements. [#11218](https://github.com/handsontable/handsontable/pull/11218)
|
|
663
648
|
|
|
664
649
|
### Fixed
|
|
665
650
|
- Fixed the Autocomplete and Dropdown editors' container size calculations. [#11201](https://github.com/handsontable/handsontable/pull/11201)
|
|
@@ -682,7 +667,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
682
667
|
|
|
683
668
|
## [14.6.2] - 2025-02-10
|
|
684
669
|
|
|
685
|
-
|
|
670
|
+
### Fixed
|
|
686
671
|
- Fixed the copy/paste feature not working correctly in Chrome 133. [#11428](https://github.com/handsontable/handsontable/pull/11428)
|
|
687
672
|
|
|
688
673
|
## [14.6.1] - 2024-10-17
|
|
@@ -732,10 +717,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
732
717
|
- Improved the rendering performance. [#11069](https://github.com/handsontable/handsontable/pull/11069)
|
|
733
718
|
|
|
734
719
|
### Fixed
|
|
735
|
-
- Fixed Context.getShortcuts type. [#10910](https://github.com/handsontable/handsontable/pull/10910)
|
|
736
720
|
- Improved performance of cell merging. [#10995](https://github.com/handsontable/handsontable/pull/10995)
|
|
737
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)
|
|
738
|
-
- Fixed a bug that prevented column sorting of the checkbox cell types. [#11004](https://github.com/handsontable/handsontable/pull/11004)
|
|
739
722
|
- Fixed merged cells misalignment in overlays. [#11007](https://github.com/handsontable/handsontable/pull/11007)
|
|
740
723
|
- Fixed selection expansion for merged cells. [#11010](https://github.com/handsontable/handsontable/pull/11010)
|
|
741
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)
|
|
@@ -946,7 +929,6 @@ For more information on Handsontable 14.1.0, see:
|
|
|
946
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)
|
|
947
930
|
- Extended the Core's `scrollViewportTo` method to allow disabling of cell auto-snapping. [#10508](https://github.com/handsontable/handsontable/pull/10508)
|
|
948
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)
|
|
949
|
-
- Upgraded the monorepo to utilize Node 20. [#10468](https://github.com/handsontable/handsontable/pull/10468)
|
|
950
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)
|
|
951
933
|
- Improved the performance of the table for cases when the table is hidden. [#10490](https://github.com/handsontable/handsontable/pull/10490)
|
|
952
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,
|