handsontable 15.3.0-next-175012b-20250429 → 16.0.0-next-f486b48-20250702

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/3rdparty/walkontable/src/core/_base.js +0 -3
  2. package/3rdparty/walkontable/src/core/_base.mjs +0 -3
  3. package/3rdparty/walkontable/src/core/clone.js +0 -1
  4. package/3rdparty/walkontable/src/core/clone.mjs +0 -1
  5. package/3rdparty/walkontable/src/core/core.js +0 -2
  6. package/3rdparty/walkontable/src/core/core.mjs +0 -2
  7. package/3rdparty/walkontable/src/facade/core.js +0 -3
  8. package/3rdparty/walkontable/src/facade/core.mjs +0 -3
  9. package/3rdparty/walkontable/src/index.js +1 -2
  10. package/3rdparty/walkontable/src/overlay/_base.js +1 -3
  11. package/3rdparty/walkontable/src/overlay/_base.mjs +1 -3
  12. package/3rdparty/walkontable/src/overlay/bottom.js +2 -2
  13. package/3rdparty/walkontable/src/overlay/bottom.mjs +2 -2
  14. package/3rdparty/walkontable/src/overlay/top.js +1 -1
  15. package/3rdparty/walkontable/src/overlay/top.mjs +1 -1
  16. package/3rdparty/walkontable/src/renderer/columnHeaders.js +1 -1
  17. package/3rdparty/walkontable/src/renderer/columnHeaders.mjs +2 -2
  18. package/3rdparty/walkontable/src/selection/border/border.js +17 -11
  19. package/3rdparty/walkontable/src/selection/border/border.mjs +17 -11
  20. package/3rdparty/walkontable/src/selection/border/utils.js +1 -1
  21. package/3rdparty/walkontable/src/selection/border/utils.mjs +1 -1
  22. package/3rdparty/walkontable/src/settings.js +3 -1
  23. package/3rdparty/walkontable/src/settings.mjs +3 -1
  24. package/3rdparty/walkontable/src/table.js +9 -6
  25. package/3rdparty/walkontable/src/table.mjs +9 -6
  26. package/3rdparty/walkontable/src/types.js +0 -1
  27. package/3rdparty/walkontable/src/types.mjs +0 -1
  28. package/3rdparty/walkontable/src/utils/column.js +1 -1
  29. package/3rdparty/walkontable/src/utils/column.mjs +1 -1
  30. package/3rdparty/walkontable/src/viewport.js +1 -1
  31. package/3rdparty/walkontable/src/viewport.mjs +1 -1
  32. package/CHANGELOG.md +23 -0
  33. package/README.md +10 -4
  34. package/base.js +2 -2
  35. package/base.mjs +2 -2
  36. package/cellTypes/registry.js +2 -3
  37. package/cellTypes/registry.mjs +1 -1
  38. package/core/coordsMapper/rangeToRenderableMapper.js +124 -0
  39. package/core/coordsMapper/rangeToRenderableMapper.mjs +120 -0
  40. package/core/focusCatcher/focusDetector.js +2 -2
  41. package/core/focusCatcher/focusDetector.mjs +2 -2
  42. package/core/hooks/constants.js +259 -1
  43. package/core/hooks/constants.mjs +259 -1
  44. package/core.d.ts +2 -0
  45. package/core.js +202 -58
  46. package/core.mjs +202 -58
  47. package/dataMap/dataMap.js +16 -30
  48. package/dataMap/dataMap.mjs +16 -30
  49. package/dataMap/metaManager/metaSchema.js +58 -0
  50. package/dataMap/metaManager/metaSchema.mjs +58 -0
  51. package/dist/handsontable.css +30 -4
  52. package/dist/handsontable.full.css +30 -4
  53. package/dist/handsontable.full.js +6073 -4352
  54. package/dist/handsontable.full.min.css +3 -3
  55. package/dist/handsontable.full.min.js +206 -206
  56. package/dist/handsontable.js +5751 -4037
  57. package/dist/handsontable.min.css +3 -3
  58. package/dist/handsontable.min.js +41 -41
  59. package/dist/languages/all.min.js +1 -1
  60. package/dist/languages/ar-AR.min.js +1 -1
  61. package/dist/languages/cs-CZ.min.js +1 -1
  62. package/dist/languages/de-CH.min.js +1 -1
  63. package/dist/languages/de-DE.min.js +1 -1
  64. package/dist/languages/en-US.min.js +1 -1
  65. package/dist/languages/es-MX.min.js +1 -1
  66. package/dist/languages/fa-IR.min.js +1 -1
  67. package/dist/languages/fr-FR.min.js +1 -1
  68. package/dist/languages/hr-HR.min.js +1 -1
  69. package/dist/languages/it-IT.min.js +1 -1
  70. package/dist/languages/ja-JP.min.js +1 -1
  71. package/dist/languages/ko-KR.min.js +1 -1
  72. package/dist/languages/lv-LV.min.js +1 -1
  73. package/dist/languages/nb-NO.min.js +1 -1
  74. package/dist/languages/nl-NL.min.js +1 -1
  75. package/dist/languages/pl-PL.min.js +1 -1
  76. package/dist/languages/pt-BR.min.js +1 -1
  77. package/dist/languages/ru-RU.min.js +1 -1
  78. package/dist/languages/sr-SP.min.js +1 -1
  79. package/dist/languages/zh-CN.min.js +1 -1
  80. package/dist/languages/zh-TW.min.js +1 -1
  81. package/editorManager.js +5 -1
  82. package/editorManager.mjs +5 -1
  83. package/editors/autocompleteEditor/autocompleteEditor.d.ts +0 -12
  84. package/editors/autocompleteEditor/autocompleteEditor.js +42 -69
  85. package/editors/autocompleteEditor/autocompleteEditor.mjs +43 -70
  86. package/editors/baseEditor/baseEditor.js +1 -1
  87. package/editors/baseEditor/baseEditor.mjs +1 -1
  88. package/editors/dateEditor/dateEditor.js +2 -8
  89. package/editors/dateEditor/dateEditor.mjs +3 -9
  90. package/editors/handsontableEditor/handsontableEditor.d.ts +8 -0
  91. package/editors/handsontableEditor/handsontableEditor.js +173 -17
  92. package/editors/handsontableEditor/handsontableEditor.mjs +173 -17
  93. package/editors/passwordEditor/passwordEditor.js +2 -0
  94. package/editors/passwordEditor/passwordEditor.mjs +2 -0
  95. package/editors/registry.js +2 -3
  96. package/editors/registry.mjs +1 -1
  97. package/editors/textEditor/textEditor.js +2 -0
  98. package/editors/textEditor/textEditor.mjs +2 -0
  99. package/helpers/a11y.js +2 -0
  100. package/helpers/a11y.mjs +1 -0
  101. package/helpers/dom/element.d.ts +1 -0
  102. package/helpers/dom/element.js +26 -1
  103. package/helpers/dom/element.mjs +25 -1
  104. package/helpers/mixed.js +4 -4
  105. package/helpers/mixed.mjs +4 -4
  106. package/i18n/languages/ar-AR.js +1 -2
  107. package/i18n/languages/cs-CZ.js +1 -2
  108. package/i18n/languages/de-CH.js +1 -2
  109. package/i18n/languages/de-DE.js +1 -2
  110. package/i18n/languages/en-US.js +1 -2
  111. package/i18n/languages/es-MX.js +1 -2
  112. package/i18n/languages/fa-IR.js +1 -2
  113. package/i18n/languages/fr-FR.js +1 -2
  114. package/i18n/languages/hr-HR.js +1 -2
  115. package/i18n/languages/it-IT.js +1 -2
  116. package/i18n/languages/ja-JP.js +1 -2
  117. package/i18n/languages/ko-KR.js +1 -2
  118. package/i18n/languages/lv-LV.js +1 -2
  119. package/i18n/languages/nb-NO.js +1 -2
  120. package/i18n/languages/nl-NL.js +1 -2
  121. package/i18n/languages/pl-PL.js +1 -2
  122. package/i18n/languages/pt-BR.js +1 -2
  123. package/i18n/languages/ru-RU.js +1 -2
  124. package/i18n/languages/sr-SP.js +1 -2
  125. package/i18n/languages/zh-CN.js +1 -2
  126. package/i18n/languages/zh-TW.js +1 -2
  127. package/i18n/phraseFormatters/index.js +2 -2
  128. package/i18n/phraseFormatters/index.mjs +1 -1
  129. package/i18n/registry.js +3 -4
  130. package/i18n/registry.mjs +1 -1
  131. package/index.js +1 -2
  132. package/package.json +10 -4
  133. package/plugins/autoColumnSize/autoColumnSize.js +47 -0
  134. package/plugins/autoColumnSize/autoColumnSize.mjs +47 -0
  135. package/plugins/autoRowSize/autoRowSize.js +45 -0
  136. package/plugins/autoRowSize/autoRowSize.mjs +45 -0
  137. package/plugins/bindRowsWithHeaders/bindRowsWithHeaders.js +13 -0
  138. package/plugins/bindRowsWithHeaders/bindRowsWithHeaders.mjs +13 -0
  139. package/plugins/collapsibleColumns/collapsibleColumns.js +31 -0
  140. package/plugins/collapsibleColumns/collapsibleColumns.mjs +31 -0
  141. package/plugins/columnSorting/sortService/registry.js +3 -4
  142. package/plugins/columnSorting/sortService/registry.mjs +1 -1
  143. package/plugins/columnSummary/columnSummary.js +33 -0
  144. package/plugins/columnSummary/columnSummary.mjs +33 -0
  145. package/plugins/comments/commentEditor.js +8 -2
  146. package/plugins/comments/commentEditor.mjs +8 -2
  147. package/plugins/comments/comments.js +59 -15
  148. package/plugins/comments/comments.mjs +60 -16
  149. package/plugins/comments/contextMenuItem/addEditComment.js +1 -2
  150. package/plugins/comments/contextMenuItem/readOnlyComment.js +1 -2
  151. package/plugins/comments/contextMenuItem/removeComment.js +1 -2
  152. package/plugins/contextMenu/contextMenu.js +1 -1
  153. package/plugins/contextMenu/contextMenu.mjs +1 -1
  154. package/plugins/contextMenu/menu/menu.js +12 -6
  155. package/plugins/contextMenu/menu/menu.mjs +13 -7
  156. package/plugins/contextMenu/predefinedItems/alignment.js +1 -2
  157. package/plugins/contextMenu/predefinedItems/clearColumn.js +1 -2
  158. package/plugins/contextMenu/predefinedItems/columnLeft.js +1 -2
  159. package/plugins/contextMenu/predefinedItems/columnRight.js +1 -2
  160. package/plugins/contextMenu/predefinedItems/index.js +1 -2
  161. package/plugins/contextMenu/predefinedItems/readOnly.js +1 -2
  162. package/plugins/contextMenu/predefinedItems/redo.js +1 -2
  163. package/plugins/contextMenu/predefinedItems/removeColumn.js +1 -2
  164. package/plugins/contextMenu/predefinedItems/removeRow.js +1 -2
  165. package/plugins/contextMenu/predefinedItems/rowAbove.js +1 -2
  166. package/plugins/contextMenu/predefinedItems/rowBelow.js +1 -2
  167. package/plugins/contextMenu/predefinedItems/undo.js +1 -2
  168. package/plugins/copyPaste/contextMenuItem/cut.js +1 -2
  169. package/plugins/customBorders/contextMenuItem/bottom.js +1 -2
  170. package/plugins/customBorders/contextMenuItem/left.js +1 -2
  171. package/plugins/customBorders/contextMenuItem/noBorders.js +1 -2
  172. package/plugins/customBorders/contextMenuItem/right.js +1 -2
  173. package/plugins/customBorders/contextMenuItem/top.js +1 -2
  174. package/plugins/customBorders/customBorders.js +1 -2
  175. package/plugins/dropdownMenu/dropdownMenu.js +16 -1
  176. package/plugins/dropdownMenu/dropdownMenu.mjs +16 -1
  177. package/plugins/exportFile/exportFile.js +59 -2
  178. package/plugins/exportFile/exportFile.mjs +58 -0
  179. package/plugins/filters/component/actionBar.js +1 -2
  180. package/plugins/filters/component/condition.js +1 -2
  181. package/plugins/filters/component/value.js +1 -2
  182. package/plugins/filters/condition/beginsWith.js +1 -2
  183. package/plugins/filters/condition/between.js +1 -2
  184. package/plugins/filters/condition/contains.js +1 -2
  185. package/plugins/filters/condition/date/after.js +1 -2
  186. package/plugins/filters/condition/date/before.js +1 -2
  187. package/plugins/filters/condition/date/today.js +1 -2
  188. package/plugins/filters/condition/date/tomorrow.js +1 -2
  189. package/plugins/filters/condition/date/yesterday.js +1 -2
  190. package/plugins/filters/condition/empty.js +1 -2
  191. package/plugins/filters/condition/endsWith.js +1 -2
  192. package/plugins/filters/condition/equal.js +1 -2
  193. package/plugins/filters/condition/greaterThan.js +1 -2
  194. package/plugins/filters/condition/greaterThanOrEqual.js +1 -2
  195. package/plugins/filters/condition/lessThan.js +1 -2
  196. package/plugins/filters/condition/lessThanOrEqual.js +1 -2
  197. package/plugins/filters/condition/none.js +1 -2
  198. package/plugins/filters/condition/notBetween.js +1 -2
  199. package/plugins/filters/condition/notContains.js +1 -2
  200. package/plugins/filters/condition/notEmpty.js +1 -2
  201. package/plugins/filters/condition/notEqual.js +1 -2
  202. package/plugins/filters/filters.js +76 -3
  203. package/plugins/filters/filters.mjs +75 -1
  204. package/plugins/filters/logicalOperations/conjunction.js +1 -2
  205. package/plugins/filters/logicalOperations/disjunction.js +1 -2
  206. package/plugins/filters/logicalOperations/disjunctionWithExtraCondition.js +1 -2
  207. package/plugins/filters/ui/_base.js +1 -2
  208. package/plugins/filters/ui/multipleSelect.js +1 -7
  209. package/plugins/filters/ui/multipleSelect.mjs +0 -5
  210. package/plugins/filters/ui/select.js +1 -2
  211. package/plugins/formulas/engine/register.js +3 -4
  212. package/plugins/formulas/engine/register.mjs +1 -1
  213. package/plugins/formulas/formulas.js +40 -41
  214. package/plugins/formulas/formulas.mjs +39 -40
  215. package/plugins/hiddenColumns/contextMenuItem/hideColumn.js +1 -2
  216. package/plugins/hiddenColumns/contextMenuItem/showColumn.js +1 -2
  217. package/plugins/hiddenColumns/hiddenColumns.js +64 -0
  218. package/plugins/hiddenColumns/hiddenColumns.mjs +64 -0
  219. package/plugins/hiddenRows/contextMenuItem/hideRow.js +1 -2
  220. package/plugins/hiddenRows/contextMenuItem/showRow.js +1 -2
  221. package/plugins/hiddenRows/hiddenRows.js +64 -0
  222. package/plugins/hiddenRows/hiddenRows.mjs +64 -0
  223. package/plugins/manualColumnFreeze/contextMenuItem/freezeColumn.js +1 -2
  224. package/plugins/manualColumnFreeze/contextMenuItem/unfreezeColumn.js +1 -2
  225. package/plugins/manualRowMove/manualRowMove.js +1 -1
  226. package/plugins/manualRowMove/manualRowMove.mjs +1 -1
  227. package/plugins/manualRowResize/manualRowResize.js +1 -1
  228. package/plugins/manualRowResize/manualRowResize.mjs +1 -1
  229. package/plugins/mergeCells/contextMenuItem/toggleMerge.js +1 -2
  230. package/plugins/mergeCells/mergeCells.js +56 -38
  231. package/plugins/mergeCells/mergeCells.mjs +56 -38
  232. package/plugins/mergeCells/utils.js +3 -4
  233. package/plugins/mergeCells/utils.mjs +3 -4
  234. package/plugins/nestedHeaders/nestedHeaders.js +37 -12
  235. package/plugins/nestedHeaders/nestedHeaders.mjs +37 -12
  236. package/plugins/nestedRows/nestedRows.js +12 -12
  237. package/plugins/nestedRows/nestedRows.mjs +12 -12
  238. package/plugins/nestedRows/ui/contextMenu.js +1 -2
  239. package/plugins/nestedRows/ui/headers.js +2 -3
  240. package/plugins/nestedRows/ui/headers.mjs +2 -3
  241. package/plugins/persistentState/persistentState.js +1 -1
  242. package/plugins/persistentState/persistentState.mjs +1 -1
  243. package/plugins/stretchColumns/calculator.js +3 -2
  244. package/plugins/stretchColumns/calculator.mjs +3 -2
  245. package/plugins/stretchColumns/stretchColumns.js +13 -0
  246. package/plugins/stretchColumns/stretchColumns.mjs +13 -0
  247. package/plugins/trimRows/trimRows.js +61 -0
  248. package/plugins/trimRows/trimRows.mjs +61 -0
  249. package/renderers/baseRenderer/baseRenderer.js +4 -0
  250. package/renderers/baseRenderer/baseRenderer.mjs +4 -0
  251. package/renderers/registry.js +2 -3
  252. package/renderers/registry.mjs +1 -1
  253. package/selection/mouseEventHandler.js +48 -13
  254. package/selection/mouseEventHandler.mjs +47 -13
  255. package/selection/range.js +73 -6
  256. package/selection/range.mjs +73 -6
  257. package/selection/selection.js +46 -32
  258. package/selection/selection.mjs +45 -30
  259. package/settings.d.ts +1 -0
  260. package/styles/handsontable.css +131 -55
  261. package/styles/handsontable.min.css +3 -3
  262. package/styles/ht-theme-horizon.css +296 -181
  263. package/styles/ht-theme-horizon.min.css +3 -3
  264. package/styles/ht-theme-main.css +314 -205
  265. package/styles/ht-theme-main.min.css +3 -3
  266. package/tableView.js +9 -20
  267. package/tableView.mjs +9 -20
  268. package/translations/indexMapper.js +9 -5
  269. package/translations/indexMapper.mjs +9 -5
  270. package/utils/paginator.js +13 -0
  271. package/utils/paginator.mjs +13 -0
  272. package/utils/staticRegister.js +24 -2
  273. package/utils/staticRegister.mjs +23 -2
  274. package/{3rdparty/walkontable/src/utils → utils}/stylesHandler.js +16 -30
  275. package/{3rdparty/walkontable/src/utils → utils}/stylesHandler.mjs +16 -30
  276. package/validators/registry.js +2 -3
  277. package/validators/registry.mjs +1 -1
@@ -285,7 +285,6 @@ class AutocompleteEditor extends _handsontableEditor.HandsontableEditor {
285
285
  /**
286
286
  * Prepares choices list based on applied argument.
287
287
  *
288
- * @private
289
288
  * @param {string} query The query.
290
289
  */
291
290
  queryChoices(query) {
@@ -350,7 +349,7 @@ class AutocompleteEditor extends _handsontableEditor.HandsontableEditor {
350
349
  this.htEditor.loadData((0, _array.pivot)([choices]));
351
350
  if (choices.length > 0) {
352
351
  this.updateDropdownDimensions();
353
- this.flipDropdownIfNeeded();
352
+ this.flipDropdownVerticallyIfNeeded();
354
353
  if (this.cellProperties.strict === true) {
355
354
  this.highlightBestMatchingChoice(highlightIndex);
356
355
  }
@@ -360,29 +359,20 @@ class AutocompleteEditor extends _handsontableEditor.HandsontableEditor {
360
359
  }
361
360
 
362
361
  /**
363
- * Checks where is enough place to open editor.
362
+ * Calculates the space above and below the editor and flips it vertically if needed.
364
363
  *
365
364
  * @private
366
- * @returns {boolean}
365
+ * @returns {{ isFlipped: boolean, spaceAbove: number, spaceBelow: number}}
367
366
  */
368
- flipDropdownIfNeeded() {
369
- const editorRect = this.getEditedCellRect();
370
- const editorHeight = editorRect.height;
371
- let spaceAbove = editorRect.top;
372
- if (this.hot.view.isVerticallyScrollableByWindow()) {
373
- const topOffset = this.hot.view.getTableOffset().top - this.hot.rootWindow.scrollY;
374
- spaceAbove = Math.max(spaceAbove + topOffset, 0);
375
- }
376
- const dropdownHeight = this.getHeight();
377
- const spaceBelow = this.hot.view.getWorkspaceHeight() - spaceAbove - editorHeight;
378
- const flipNeeded = dropdownHeight > spaceBelow && spaceAbove > spaceBelow + editorHeight;
379
- if (flipNeeded) {
380
- this.flipDropdown(dropdownHeight);
381
- } else {
382
- this.unflipDropdown();
383
- }
384
- this.limitDropdownIfNeeded(flipNeeded ? spaceAbove : spaceBelow, dropdownHeight);
385
- return flipNeeded;
367
+ flipDropdownVerticallyIfNeeded() {
368
+ const result = super.flipDropdownVerticallyIfNeeded();
369
+ const {
370
+ isFlipped,
371
+ spaceAbove,
372
+ spaceBelow
373
+ } = result;
374
+ this.limitDropdownIfNeeded(isFlipped ? spaceAbove : spaceBelow);
375
+ return result;
386
376
  }
387
377
 
388
378
  /**
@@ -390,60 +380,36 @@ class AutocompleteEditor extends _handsontableEditor.HandsontableEditor {
390
380
  *
391
381
  * @private
392
382
  * @param {number} spaceAvailable The free space as height defined in px available for dropdown list.
393
- * @param {number} dropdownHeight The dropdown height.
394
383
  */
395
- limitDropdownIfNeeded(spaceAvailable, dropdownHeight) {
384
+ limitDropdownIfNeeded(spaceAvailable) {
385
+ const dropdownHeight = this.getDropdownHeight();
396
386
  if (dropdownHeight > spaceAvailable) {
397
387
  let tempHeight = 0;
398
- let i = 0;
399
388
  let lastRowHeight = 0;
400
389
  let height = null;
401
390
  do {
402
- lastRowHeight = this.htEditor.getRowHeight(i) || this.htEditor.view.getDefaultRowHeight();
391
+ lastRowHeight = this.htEditor.stylesHandler.getDefaultRowHeight();
403
392
  tempHeight += lastRowHeight;
404
- i += 1;
405
393
  } while (tempHeight < spaceAvailable);
406
394
  height = tempHeight - lastRowHeight;
407
- if (this.htEditor.flipped) {
395
+ if (this.isFlippedVertically) {
408
396
  this.htEditor.rootElement.style.top = `${parseInt(this.htEditor.rootElement.style.top, 10) + dropdownHeight - height}px`;
409
397
  }
410
398
  this.setDropdownHeight(tempHeight - lastRowHeight);
411
399
  }
412
400
  }
413
-
414
- /**
415
- * Configures editor to open it at the top.
416
- *
417
- * @private
418
- * @param {number} dropdownHeight The dropdown height.
419
- */
420
- flipDropdown(dropdownHeight) {
421
- const dropdownStyle = this.htEditor.rootElement.style;
422
- dropdownStyle.position = 'absolute';
423
- dropdownStyle.top = `${-dropdownHeight}px`;
424
- this.htEditor.flipped = true;
425
- }
426
-
427
- /**
428
- * Configures editor to open it at the bottom.
429
- *
430
- * @private
431
- */
432
- unflipDropdown() {
433
- const dropdownStyle = this.htEditor.rootElement.style;
434
- dropdownStyle.position = 'absolute';
435
- dropdownStyle.top = '';
436
- this.htEditor.flipped = undefined;
437
- }
438
401
  /**
439
402
  * Updates width and height of the internal Handsontable's instance.
440
403
  *
441
404
  * @private
442
405
  */
443
406
  updateDropdownDimensions() {
407
+ const fractionalScalingCompensation = (0, _element.getFractionalScalingCompensation)();
408
+ const targetWidth = this.getTargetEditorWidth() + fractionalScalingCompensation;
409
+ const targetHeight = this.getTargetEditorHeight() + fractionalScalingCompensation;
444
410
  this.htEditor.updateSettings({
445
- width: this.getWidth(),
446
- height: this.getHeight()
411
+ width: targetWidth,
412
+ height: targetHeight
447
413
  });
448
414
  _assertClassBrand(_AutocompleteEditor_brand, this, _fixDropdownWidth).call(this);
449
415
  this.htEditor.view._wt.wtTable.alignOverlaysWithTrimmingContainer();
@@ -478,34 +444,41 @@ class AutocompleteEditor extends _handsontableEditor.HandsontableEditor {
478
444
  }
479
445
 
480
446
  /**
481
- * Calculates and return the internal Handsontable's height.
447
+ * Calculates the proposed/target editor height that should be set once the editor is opened.
448
+ * The method may be overwritten in the child class to provide a custom size logic.
482
449
  *
483
- * @private
484
450
  * @returns {number}
485
451
  */
486
- getHeight() {
487
- const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
488
- const borderVerticalCompensation = parseInt(containerStyle.borderTopWidth, 10) + parseInt(containerStyle.borderBottomWidth, 10);
452
+ getTargetEditorHeight() {
453
+ let borderCompensation = 0;
454
+ if (!this.hot.getCurrentThemeName()) {
455
+ const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
456
+ borderCompensation = parseInt(containerStyle.borderTopWidth, 10) + parseInt(containerStyle.borderBottomWidth, 10);
457
+ }
489
458
  const maxItems = Math.min(this.cellProperties.visibleRows, this.strippedChoices.length);
490
459
  const height = Array.from({
491
460
  length: maxItems
492
461
  }, (_, i) => i).reduce((totalHeight, index) => {
493
- const rowHeight = this.htEditor.getRowHeight(index) || this.htEditor.view.getDefaultRowHeight();
462
+ // for the first row, we need to add 1px (border-top compensation)
463
+ const rowHeight = this.hot.stylesHandler.getDefaultRowHeight() + (index === 0 ? 1 : 0);
494
464
  return totalHeight + rowHeight;
495
465
  }, 0);
496
- return height + borderVerticalCompensation + 1;
466
+ return height + borderCompensation;
497
467
  }
498
468
 
499
469
  /**
500
- * Calculates and return the internal Handsontable's width.
470
+ * Calculates the proposed/target editor width that should be set once the editor is opened.
471
+ * The method may be overwritten in the child class to provide a custom size logic.
501
472
  *
502
- * @private
503
473
  * @returns {number}
504
474
  */
505
- getWidth() {
506
- const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
507
- const borderHorizontalCompensation = parseInt(containerStyle.borderInlineStartWidth, 10) + parseInt(containerStyle.borderInlineEndWidth, 10);
508
- return this.htEditor.getColWidth(0) + borderHorizontalCompensation;
475
+ getTargetEditorWidth() {
476
+ let borderCompensation = 0;
477
+ if (!this.hot.getCurrentThemeName()) {
478
+ const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
479
+ borderCompensation = parseInt(containerStyle.borderInlineStartWidth, 10) + parseInt(containerStyle.borderInlineEndWidth, 10);
480
+ }
481
+ return this.htEditor.getColWidth(0) + borderCompensation;
509
482
  }
510
483
 
511
484
  /**
@@ -590,7 +563,7 @@ exports.AutocompleteEditor = AutocompleteEditor;
590
563
  function _fixDropdownWidth() {
591
564
  if (this.htEditor.view.hasVerticalScroll()) {
592
565
  this.htEditor.updateSettings({
593
- width: this.getWidth() + (0, _element.getScrollbarWidth)(this.hot.rootDocument)
566
+ width: this.getTargetEditorWidth() + (0, _element.getScrollbarWidth)(this.hot.rootDocument)
594
567
  });
595
568
  }
596
569
  }
@@ -14,7 +14,7 @@ function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
14
14
  function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
15
15
  import { HandsontableEditor } from "../handsontableEditor/index.mjs";
16
16
  import { arrayMap, pivot } from "../../helpers/array.mjs";
17
- import { addClass, getCaretPosition, getScrollbarWidth, getSelectionEndPosition, outerWidth, setAttribute, setCaretPosition } from "../../helpers/dom/element.mjs";
17
+ import { addClass, getCaretPosition, getFractionalScalingCompensation, getScrollbarWidth, getSelectionEndPosition, outerWidth, setAttribute, setCaretPosition } from "../../helpers/dom/element.mjs";
18
18
  import { isDefined, stringify } from "../../helpers/mixed.mjs";
19
19
  import { stripTags } from "../../helpers/string.mjs";
20
20
  import { KEY_CODES, isPrintableChar } from "../../helpers/unicode.mjs";
@@ -282,7 +282,6 @@ export class AutocompleteEditor extends HandsontableEditor {
282
282
  /**
283
283
  * Prepares choices list based on applied argument.
284
284
  *
285
- * @private
286
285
  * @param {string} query The query.
287
286
  */
288
287
  queryChoices(query) {
@@ -347,7 +346,7 @@ export class AutocompleteEditor extends HandsontableEditor {
347
346
  this.htEditor.loadData(pivot([choices]));
348
347
  if (choices.length > 0) {
349
348
  this.updateDropdownDimensions();
350
- this.flipDropdownIfNeeded();
349
+ this.flipDropdownVerticallyIfNeeded();
351
350
  if (this.cellProperties.strict === true) {
352
351
  this.highlightBestMatchingChoice(highlightIndex);
353
352
  }
@@ -357,29 +356,20 @@ export class AutocompleteEditor extends HandsontableEditor {
357
356
  }
358
357
 
359
358
  /**
360
- * Checks where is enough place to open editor.
359
+ * Calculates the space above and below the editor and flips it vertically if needed.
361
360
  *
362
361
  * @private
363
- * @returns {boolean}
362
+ * @returns {{ isFlipped: boolean, spaceAbove: number, spaceBelow: number}}
364
363
  */
365
- flipDropdownIfNeeded() {
366
- const editorRect = this.getEditedCellRect();
367
- const editorHeight = editorRect.height;
368
- let spaceAbove = editorRect.top;
369
- if (this.hot.view.isVerticallyScrollableByWindow()) {
370
- const topOffset = this.hot.view.getTableOffset().top - this.hot.rootWindow.scrollY;
371
- spaceAbove = Math.max(spaceAbove + topOffset, 0);
372
- }
373
- const dropdownHeight = this.getHeight();
374
- const spaceBelow = this.hot.view.getWorkspaceHeight() - spaceAbove - editorHeight;
375
- const flipNeeded = dropdownHeight > spaceBelow && spaceAbove > spaceBelow + editorHeight;
376
- if (flipNeeded) {
377
- this.flipDropdown(dropdownHeight);
378
- } else {
379
- this.unflipDropdown();
380
- }
381
- this.limitDropdownIfNeeded(flipNeeded ? spaceAbove : spaceBelow, dropdownHeight);
382
- return flipNeeded;
364
+ flipDropdownVerticallyIfNeeded() {
365
+ const result = super.flipDropdownVerticallyIfNeeded();
366
+ const {
367
+ isFlipped,
368
+ spaceAbove,
369
+ spaceBelow
370
+ } = result;
371
+ this.limitDropdownIfNeeded(isFlipped ? spaceAbove : spaceBelow);
372
+ return result;
383
373
  }
384
374
 
385
375
  /**
@@ -387,60 +377,36 @@ export class AutocompleteEditor extends HandsontableEditor {
387
377
  *
388
378
  * @private
389
379
  * @param {number} spaceAvailable The free space as height defined in px available for dropdown list.
390
- * @param {number} dropdownHeight The dropdown height.
391
380
  */
392
- limitDropdownIfNeeded(spaceAvailable, dropdownHeight) {
381
+ limitDropdownIfNeeded(spaceAvailable) {
382
+ const dropdownHeight = this.getDropdownHeight();
393
383
  if (dropdownHeight > spaceAvailable) {
394
384
  let tempHeight = 0;
395
- let i = 0;
396
385
  let lastRowHeight = 0;
397
386
  let height = null;
398
387
  do {
399
- lastRowHeight = this.htEditor.getRowHeight(i) || this.htEditor.view.getDefaultRowHeight();
388
+ lastRowHeight = this.htEditor.stylesHandler.getDefaultRowHeight();
400
389
  tempHeight += lastRowHeight;
401
- i += 1;
402
390
  } while (tempHeight < spaceAvailable);
403
391
  height = tempHeight - lastRowHeight;
404
- if (this.htEditor.flipped) {
392
+ if (this.isFlippedVertically) {
405
393
  this.htEditor.rootElement.style.top = `${parseInt(this.htEditor.rootElement.style.top, 10) + dropdownHeight - height}px`;
406
394
  }
407
395
  this.setDropdownHeight(tempHeight - lastRowHeight);
408
396
  }
409
397
  }
410
-
411
- /**
412
- * Configures editor to open it at the top.
413
- *
414
- * @private
415
- * @param {number} dropdownHeight The dropdown height.
416
- */
417
- flipDropdown(dropdownHeight) {
418
- const dropdownStyle = this.htEditor.rootElement.style;
419
- dropdownStyle.position = 'absolute';
420
- dropdownStyle.top = `${-dropdownHeight}px`;
421
- this.htEditor.flipped = true;
422
- }
423
-
424
- /**
425
- * Configures editor to open it at the bottom.
426
- *
427
- * @private
428
- */
429
- unflipDropdown() {
430
- const dropdownStyle = this.htEditor.rootElement.style;
431
- dropdownStyle.position = 'absolute';
432
- dropdownStyle.top = '';
433
- this.htEditor.flipped = undefined;
434
- }
435
398
  /**
436
399
  * Updates width and height of the internal Handsontable's instance.
437
400
  *
438
401
  * @private
439
402
  */
440
403
  updateDropdownDimensions() {
404
+ const fractionalScalingCompensation = getFractionalScalingCompensation();
405
+ const targetWidth = this.getTargetEditorWidth() + fractionalScalingCompensation;
406
+ const targetHeight = this.getTargetEditorHeight() + fractionalScalingCompensation;
441
407
  this.htEditor.updateSettings({
442
- width: this.getWidth(),
443
- height: this.getHeight()
408
+ width: targetWidth,
409
+ height: targetHeight
444
410
  });
445
411
  _assertClassBrand(_AutocompleteEditor_brand, this, _fixDropdownWidth).call(this);
446
412
  this.htEditor.view._wt.wtTable.alignOverlaysWithTrimmingContainer();
@@ -475,34 +441,41 @@ export class AutocompleteEditor extends HandsontableEditor {
475
441
  }
476
442
 
477
443
  /**
478
- * Calculates and return the internal Handsontable's height.
444
+ * Calculates the proposed/target editor height that should be set once the editor is opened.
445
+ * The method may be overwritten in the child class to provide a custom size logic.
479
446
  *
480
- * @private
481
447
  * @returns {number}
482
448
  */
483
- getHeight() {
484
- const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
485
- const borderVerticalCompensation = parseInt(containerStyle.borderTopWidth, 10) + parseInt(containerStyle.borderBottomWidth, 10);
449
+ getTargetEditorHeight() {
450
+ let borderCompensation = 0;
451
+ if (!this.hot.getCurrentThemeName()) {
452
+ const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
453
+ borderCompensation = parseInt(containerStyle.borderTopWidth, 10) + parseInt(containerStyle.borderBottomWidth, 10);
454
+ }
486
455
  const maxItems = Math.min(this.cellProperties.visibleRows, this.strippedChoices.length);
487
456
  const height = Array.from({
488
457
  length: maxItems
489
458
  }, (_, i) => i).reduce((totalHeight, index) => {
490
- const rowHeight = this.htEditor.getRowHeight(index) || this.htEditor.view.getDefaultRowHeight();
459
+ // for the first row, we need to add 1px (border-top compensation)
460
+ const rowHeight = this.hot.stylesHandler.getDefaultRowHeight() + (index === 0 ? 1 : 0);
491
461
  return totalHeight + rowHeight;
492
462
  }, 0);
493
- return height + borderVerticalCompensation + 1;
463
+ return height + borderCompensation;
494
464
  }
495
465
 
496
466
  /**
497
- * Calculates and return the internal Handsontable's width.
467
+ * Calculates the proposed/target editor width that should be set once the editor is opened.
468
+ * The method may be overwritten in the child class to provide a custom size logic.
498
469
  *
499
- * @private
500
470
  * @returns {number}
501
471
  */
502
- getWidth() {
503
- const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
504
- const borderHorizontalCompensation = parseInt(containerStyle.borderInlineStartWidth, 10) + parseInt(containerStyle.borderInlineEndWidth, 10);
505
- return this.htEditor.getColWidth(0) + borderHorizontalCompensation;
472
+ getTargetEditorWidth() {
473
+ let borderCompensation = 0;
474
+ if (!this.hot.getCurrentThemeName()) {
475
+ const containerStyle = this.hot.rootWindow.getComputedStyle(this.htContainer.querySelector('.htCore'));
476
+ borderCompensation = parseInt(containerStyle.borderInlineStartWidth, 10) + parseInt(containerStyle.borderInlineEndWidth, 10);
477
+ }
478
+ return this.htEditor.getColWidth(0) + borderCompensation;
506
479
  }
507
480
 
508
481
  /**
@@ -586,7 +559,7 @@ export class AutocompleteEditor extends HandsontableEditor {
586
559
  function _fixDropdownWidth() {
587
560
  if (this.htEditor.view.hasVerticalScroll()) {
588
561
  this.htEditor.updateSettings({
589
- width: this.getWidth() + getScrollbarWidth(this.hot.rootDocument)
562
+ width: this.getTargetEditorWidth() + getScrollbarWidth(this.hot.rootDocument)
590
563
  });
591
564
  }
592
565
  }
@@ -492,7 +492,7 @@ class BaseEditor {
492
492
  const actualVerticalScrollbarWidth = (0, _element.hasVerticalScrollbar)(scrollableContainerTop) ? scrollbarWidth : 0;
493
493
  const actualHorizontalScrollbarWidth = (0, _element.hasHorizontalScrollbar)(scrollableContainerLeft) ? scrollbarWidth : 0;
494
494
  const maxWidth = this.hot.view.maximumVisibleElementWidth(cellStartOffset) - actualVerticalScrollbarWidth + inlineStartBorderCompensation;
495
- const maxHeight = Math.max(this.hot.view.maximumVisibleElementHeight(cellTopOffset) - actualHorizontalScrollbarWidth + topBorderCompensation, this.hot.view.getDefaultRowHeight());
495
+ const maxHeight = Math.max(this.hot.view.maximumVisibleElementHeight(cellTopOffset) - actualHorizontalScrollbarWidth + topBorderCompensation, this.hot.stylesHandler.getDefaultRowHeight());
496
496
  return {
497
497
  top: topPos,
498
498
  start: inlineStartPos,
@@ -488,7 +488,7 @@ export class BaseEditor {
488
488
  const actualVerticalScrollbarWidth = hasVerticalScrollbar(scrollableContainerTop) ? scrollbarWidth : 0;
489
489
  const actualHorizontalScrollbarWidth = hasHorizontalScrollbar(scrollableContainerLeft) ? scrollbarWidth : 0;
490
490
  const maxWidth = this.hot.view.maximumVisibleElementWidth(cellStartOffset) - actualVerticalScrollbarWidth + inlineStartBorderCompensation;
491
- const maxHeight = Math.max(this.hot.view.maximumVisibleElementHeight(cellTopOffset) - actualHorizontalScrollbarWidth + topBorderCompensation, this.hot.view.getDefaultRowHeight());
491
+ const maxHeight = Math.max(this.hot.view.maximumVisibleElementHeight(cellTopOffset) - actualHorizontalScrollbarWidth + topBorderCompensation, this.hot.stylesHandler.getDefaultRowHeight());
492
492
  return {
493
493
  top: topPos,
494
494
  start: inlineStartPos,
@@ -61,8 +61,7 @@ class DateEditor extends _textEditor.TextEditor {
61
61
  });
62
62
  this.hot.addHook('afterSetTheme', (themeName, firstRun) => {
63
63
  if (!firstRun) {
64
- (0, _element.removeClass)(this.datePicker, /ht-theme-.*/g);
65
- (0, _element.addClass)(this.datePicker, themeName);
64
+ this.close();
66
65
  }
67
66
  });
68
67
  }
@@ -80,10 +79,7 @@ class DateEditor extends _textEditor.TextEditor {
80
79
  this.datePickerStyle.zIndex = 9999;
81
80
  this.datePicker.setAttribute('dir', this.hot.isRtl() ? 'rtl' : 'ltr');
82
81
  (0, _element.addClass)(this.datePicker, 'htDatepickerHolder');
83
- const themeClassName = this.hot.getCurrentThemeName();
84
- (0, _element.removeClass)(this.datePicker, /ht-theme-.*/g);
85
- (0, _element.addClass)(this.datePicker, themeClassName);
86
- this.hot.rootDocument.body.appendChild(this.datePicker);
82
+ this.hot.rootPortalElement.appendChild(this.datePicker);
87
83
 
88
84
  /**
89
85
  * Prevent recognizing clicking on datepicker as clicking outside of table.
@@ -164,8 +160,6 @@ class DateEditor extends _textEditor.TextEditor {
164
160
  */
165
161
  close() {
166
162
  var _this$$datePicker;
167
- this._opened = false;
168
-
169
163
  // If the date picker was never initialized (e.g. during autofill), there's nothing to destroy.
170
164
  if ((_this$$datePicker = this.$datePicker) !== null && _this$$datePicker !== void 0 && _this$$datePicker.destroy) {
171
165
  this.$datePicker.destroy();
@@ -9,7 +9,7 @@ import moment from 'moment';
9
9
  import Pikaday from '@handsontable/pikaday';
10
10
  import { EDITOR_STATE } from "../baseEditor/index.mjs";
11
11
  import { TextEditor } from "../textEditor/index.mjs";
12
- import { addClass, removeClass, hasClass, outerHeight, outerWidth } from "../../helpers/dom/element.mjs";
12
+ import { addClass, hasClass, outerHeight, outerWidth } from "../../helpers/dom/element.mjs";
13
13
  import { deepExtend } from "../../helpers/object.mjs";
14
14
  import { isFunctionKey } from "../../helpers/unicode.mjs";
15
15
  import { isMobileBrowser } from "../../helpers/browser.mjs";
@@ -57,8 +57,7 @@ export class DateEditor extends TextEditor {
57
57
  });
58
58
  this.hot.addHook('afterSetTheme', (themeName, firstRun) => {
59
59
  if (!firstRun) {
60
- removeClass(this.datePicker, /ht-theme-.*/g);
61
- addClass(this.datePicker, themeName);
60
+ this.close();
62
61
  }
63
62
  });
64
63
  }
@@ -76,10 +75,7 @@ export class DateEditor extends TextEditor {
76
75
  this.datePickerStyle.zIndex = 9999;
77
76
  this.datePicker.setAttribute('dir', this.hot.isRtl() ? 'rtl' : 'ltr');
78
77
  addClass(this.datePicker, 'htDatepickerHolder');
79
- const themeClassName = this.hot.getCurrentThemeName();
80
- removeClass(this.datePicker, /ht-theme-.*/g);
81
- addClass(this.datePicker, themeClassName);
82
- this.hot.rootDocument.body.appendChild(this.datePicker);
78
+ this.hot.rootPortalElement.appendChild(this.datePicker);
83
79
 
84
80
  /**
85
81
  * Prevent recognizing clicking on datepicker as clicking outside of table.
@@ -160,8 +156,6 @@ export class DateEditor extends TextEditor {
160
156
  */
161
157
  close() {
162
158
  var _this$$datePicker;
163
- this._opened = false;
164
-
165
159
  // If the date picker was never initialized (e.g. during autofill), there's nothing to destroy.
166
160
  if ((_this$$datePicker = this.$datePicker) !== null && _this$$datePicker !== void 0 && _this$$datePicker.destroy) {
167
161
  this.$datePicker.destroy();
@@ -7,4 +7,12 @@ export class HandsontableEditor extends TextEditor {
7
7
 
8
8
  htEditor: Core;
9
9
  htContainer: HTMLElement;
10
+ isFlippedVertically: boolean;
11
+ isFlippedHorizontally: boolean;
12
+
13
+ getValue(): string;
14
+ getDropdownHeight(): number;
15
+ getDropdownWidth(): number;
16
+ getTargetDropdownWidth(): number;
17
+ getTargetDropdownHeight(): number;
10
18
  }