handsontable 16.1.1 → 16.2.0-next-90d1117-20251117

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 (296) hide show
  1. package/3rdparty/walkontable/src/overlays.js +1 -1
  2. package/3rdparty/walkontable/src/overlays.mjs +1 -1
  3. package/3rdparty/walkontable/src/selection/border/border.js +19 -3
  4. package/3rdparty/walkontable/src/selection/border/border.mjs +19 -3
  5. package/CHANGELOG.md +39 -0
  6. package/base.js +2 -2
  7. package/base.mjs +2 -2
  8. package/core/coordsMapper/index.js +11 -0
  9. package/core/coordsMapper/index.mjs +1 -0
  10. package/core/hooks/bucket.js +7 -1
  11. package/core/hooks/bucket.mjs +7 -1
  12. package/core/hooks/constants.js +54 -0
  13. package/core/hooks/constants.mjs +54 -0
  14. package/core/hooks/index.d.ts +6 -0
  15. package/core/index.js +10 -4
  16. package/core/index.mjs +2 -1
  17. package/core.d.ts +3 -2
  18. package/core.js +67 -26
  19. package/core.mjs +56 -15
  20. package/dataMap/metaManager/metaSchema.js +197 -20
  21. package/dataMap/metaManager/metaSchema.mjs +197 -20
  22. package/dist/handsontable.css +175 -3
  23. package/dist/handsontable.full.css +175 -3
  24. package/dist/handsontable.full.js +10864 -8426
  25. package/dist/handsontable.full.min.css +5 -4
  26. package/dist/handsontable.full.min.js +194 -193
  27. package/dist/handsontable.js +7126 -4827
  28. package/dist/handsontable.min.css +4 -4
  29. package/dist/handsontable.min.js +43 -42
  30. package/dist/languages/all.js +168 -21
  31. package/dist/languages/all.min.js +1 -1
  32. package/dist/languages/ar-AR.js +8 -1
  33. package/dist/languages/ar-AR.min.js +1 -1
  34. package/dist/languages/cs-CZ.js +8 -1
  35. package/dist/languages/cs-CZ.min.js +1 -1
  36. package/dist/languages/de-CH.js +8 -1
  37. package/dist/languages/de-CH.min.js +1 -1
  38. package/dist/languages/de-DE.js +8 -1
  39. package/dist/languages/de-DE.min.js +1 -1
  40. package/dist/languages/en-US.js +8 -1
  41. package/dist/languages/en-US.min.js +1 -1
  42. package/dist/languages/es-MX.js +8 -1
  43. package/dist/languages/es-MX.min.js +1 -1
  44. package/dist/languages/fa-IR.js +8 -1
  45. package/dist/languages/fa-IR.min.js +1 -1
  46. package/dist/languages/fr-FR.js +8 -1
  47. package/dist/languages/fr-FR.min.js +1 -1
  48. package/dist/languages/hr-HR.js +8 -1
  49. package/dist/languages/hr-HR.min.js +1 -1
  50. package/dist/languages/it-IT.js +8 -1
  51. package/dist/languages/it-IT.min.js +1 -1
  52. package/dist/languages/ja-JP.js +8 -1
  53. package/dist/languages/ja-JP.min.js +1 -1
  54. package/dist/languages/ko-KR.js +8 -1
  55. package/dist/languages/ko-KR.min.js +1 -1
  56. package/dist/languages/lv-LV.js +8 -1
  57. package/dist/languages/lv-LV.min.js +1 -1
  58. package/dist/languages/nb-NO.js +8 -1
  59. package/dist/languages/nb-NO.min.js +1 -1
  60. package/dist/languages/nl-NL.js +8 -1
  61. package/dist/languages/nl-NL.min.js +1 -1
  62. package/dist/languages/pl-PL.js +8 -1
  63. package/dist/languages/pl-PL.min.js +1 -1
  64. package/dist/languages/pt-BR.js +8 -1
  65. package/dist/languages/pt-BR.min.js +1 -1
  66. package/dist/languages/ru-RU.js +8 -1
  67. package/dist/languages/ru-RU.min.js +1 -1
  68. package/dist/languages/sr-SP.js +8 -1
  69. package/dist/languages/sr-SP.min.js +1 -1
  70. package/dist/languages/zh-CN.js +8 -1
  71. package/dist/languages/zh-CN.min.js +1 -1
  72. package/dist/languages/zh-TW.js +8 -1
  73. package/dist/languages/zh-TW.min.js +1 -1
  74. package/editors/autocompleteEditor/autocompleteEditor.js +21 -1
  75. package/editors/autocompleteEditor/autocompleteEditor.mjs +22 -2
  76. package/focusManager/constants.js +25 -0
  77. package/focusManager/constants.mjs +22 -0
  78. package/focusManager/eventListener.js +107 -0
  79. package/focusManager/eventListener.mjs +103 -0
  80. package/{focusManager.d.ts → focusManager/grid.d.ts} +1 -1
  81. package/{focusManager.js → focusManager/grid.js} +48 -17
  82. package/{focusManager.mjs → focusManager/grid.mjs} +47 -16
  83. package/focusManager/index.d.ts +2 -0
  84. package/focusManager/index.js +20 -0
  85. package/focusManager/index.mjs +20 -0
  86. package/focusManager/scope.js +133 -0
  87. package/focusManager/scope.mjs +129 -0
  88. package/focusManager/scopeManager.d.ts +19 -0
  89. package/focusManager/scopeManager.js +268 -0
  90. package/focusManager/scopeManager.mjs +263 -0
  91. package/focusManager/scopes/grid.js +120 -0
  92. package/focusManager/scopes/grid.mjs +116 -0
  93. package/focusManager/scopes/index.js +13 -0
  94. package/focusManager/scopes/index.mjs +9 -0
  95. package/{utils → focusManager/utils}/focusDetector.js +21 -31
  96. package/{utils → focusManager/utils}/focusDetector.mjs +21 -31
  97. package/focusManager/utils/utils.js +95 -0
  98. package/focusManager/utils/utils.mjs +89 -0
  99. package/helpers/dom/element.js +1 -1
  100. package/helpers/dom/element.mjs +2 -2
  101. package/helpers/dom/event.js +1 -1
  102. package/helpers/dom/event.mjs +1 -1
  103. package/helpers/mixed.js +2 -65
  104. package/helpers/mixed.mjs +2 -63
  105. package/i18n/constants.js +10 -1
  106. package/i18n/constants.mjs +10 -1
  107. package/i18n/languages/ar-AR.js +8 -1
  108. package/i18n/languages/ar-AR.mjs +8 -1
  109. package/i18n/languages/cs-CZ.js +8 -1
  110. package/i18n/languages/cs-CZ.mjs +8 -1
  111. package/i18n/languages/de-CH.js +8 -1
  112. package/i18n/languages/de-CH.mjs +8 -1
  113. package/i18n/languages/de-DE.js +8 -1
  114. package/i18n/languages/de-DE.mjs +8 -1
  115. package/i18n/languages/en-US.js +8 -1
  116. package/i18n/languages/en-US.mjs +8 -1
  117. package/i18n/languages/es-MX.js +8 -1
  118. package/i18n/languages/es-MX.mjs +8 -1
  119. package/i18n/languages/fa-IR.js +8 -1
  120. package/i18n/languages/fa-IR.mjs +8 -1
  121. package/i18n/languages/fr-FR.js +8 -1
  122. package/i18n/languages/fr-FR.mjs +8 -1
  123. package/i18n/languages/hr-HR.js +8 -1
  124. package/i18n/languages/hr-HR.mjs +8 -1
  125. package/i18n/languages/it-IT.js +8 -1
  126. package/i18n/languages/it-IT.mjs +8 -1
  127. package/i18n/languages/ja-JP.js +8 -1
  128. package/i18n/languages/ja-JP.mjs +8 -1
  129. package/i18n/languages/ko-KR.js +8 -1
  130. package/i18n/languages/ko-KR.mjs +8 -1
  131. package/i18n/languages/lv-LV.js +8 -1
  132. package/i18n/languages/lv-LV.mjs +8 -1
  133. package/i18n/languages/nb-NO.js +8 -1
  134. package/i18n/languages/nb-NO.mjs +8 -1
  135. package/i18n/languages/nl-NL.js +8 -1
  136. package/i18n/languages/nl-NL.mjs +8 -1
  137. package/i18n/languages/pl-PL.js +8 -1
  138. package/i18n/languages/pl-PL.mjs +8 -1
  139. package/i18n/languages/pt-BR.js +8 -1
  140. package/i18n/languages/pt-BR.mjs +8 -1
  141. package/i18n/languages/ru-RU.js +8 -1
  142. package/i18n/languages/ru-RU.mjs +8 -1
  143. package/i18n/languages/sr-SP.js +8 -1
  144. package/i18n/languages/sr-SP.mjs +8 -1
  145. package/i18n/languages/zh-CN.js +8 -1
  146. package/i18n/languages/zh-CN.mjs +8 -1
  147. package/i18n/languages/zh-TW.js +8 -1
  148. package/i18n/languages/zh-TW.mjs +8 -1
  149. package/index.d.ts +9 -0
  150. package/languages/all.js +168 -21
  151. package/languages/ar-AR.js +8 -1
  152. package/languages/ar-AR.mjs +8 -1
  153. package/languages/cs-CZ.js +8 -1
  154. package/languages/cs-CZ.mjs +8 -1
  155. package/languages/de-CH.js +8 -1
  156. package/languages/de-CH.mjs +8 -1
  157. package/languages/de-DE.js +8 -1
  158. package/languages/de-DE.mjs +8 -1
  159. package/languages/en-US.js +8 -1
  160. package/languages/en-US.mjs +8 -1
  161. package/languages/es-MX.js +8 -1
  162. package/languages/es-MX.mjs +8 -1
  163. package/languages/fa-IR.js +8 -1
  164. package/languages/fa-IR.mjs +8 -1
  165. package/languages/fr-FR.js +8 -1
  166. package/languages/fr-FR.mjs +8 -1
  167. package/languages/hr-HR.js +8 -1
  168. package/languages/hr-HR.mjs +8 -1
  169. package/languages/index.js +168 -21
  170. package/languages/it-IT.js +8 -1
  171. package/languages/it-IT.mjs +8 -1
  172. package/languages/ja-JP.js +8 -1
  173. package/languages/ja-JP.mjs +8 -1
  174. package/languages/ko-KR.js +8 -1
  175. package/languages/ko-KR.mjs +8 -1
  176. package/languages/lv-LV.js +8 -1
  177. package/languages/lv-LV.mjs +8 -1
  178. package/languages/nb-NO.js +8 -1
  179. package/languages/nb-NO.mjs +8 -1
  180. package/languages/nl-NL.js +8 -1
  181. package/languages/nl-NL.mjs +8 -1
  182. package/languages/pl-PL.js +8 -1
  183. package/languages/pl-PL.mjs +8 -1
  184. package/languages/pt-BR.js +8 -1
  185. package/languages/pt-BR.mjs +8 -1
  186. package/languages/ru-RU.js +8 -1
  187. package/languages/ru-RU.mjs +8 -1
  188. package/languages/sr-SP.js +8 -1
  189. package/languages/sr-SP.mjs +8 -1
  190. package/languages/zh-CN.js +8 -1
  191. package/languages/zh-CN.mjs +8 -1
  192. package/languages/zh-TW.js +8 -1
  193. package/languages/zh-TW.mjs +8 -1
  194. package/package.json +25 -7
  195. package/plugins/autoRowSize/autoRowSize.js +8 -1
  196. package/plugins/autoRowSize/autoRowSize.mjs +8 -1
  197. package/plugins/base/base.js +36 -10
  198. package/plugins/base/base.mjs +36 -10
  199. package/plugins/columnSummary/endpoints.js +13 -3
  200. package/plugins/columnSummary/endpoints.mjs +13 -3
  201. package/plugins/customBorders/customBorders.d.ts +1 -0
  202. package/plugins/customBorders/customBorders.js +32 -2
  203. package/plugins/customBorders/customBorders.mjs +32 -2
  204. package/plugins/dialog/constants.js +7 -0
  205. package/plugins/dialog/constants.mjs +4 -0
  206. package/plugins/dialog/dialog.d.ts +22 -2
  207. package/plugins/dialog/dialog.js +197 -81
  208. package/plugins/dialog/dialog.mjs +196 -81
  209. package/plugins/dialog/templates/base.js +60 -0
  210. package/plugins/dialog/templates/base.mjs +56 -0
  211. package/plugins/dialog/templates/confirm.js +106 -0
  212. package/plugins/dialog/templates/confirm.mjs +102 -0
  213. package/plugins/dialog/templates/index.js +6 -0
  214. package/plugins/dialog/templates/index.mjs +4 -0
  215. package/plugins/dialog/ui.js +125 -41
  216. package/plugins/dialog/ui.mjs +119 -35
  217. package/plugins/emptyDataState/emptyDataState.d.ts +24 -0
  218. package/plugins/emptyDataState/emptyDataState.js +526 -0
  219. package/plugins/emptyDataState/emptyDataState.mjs +521 -0
  220. package/plugins/emptyDataState/index.d.ts +1 -0
  221. package/plugins/emptyDataState/index.js +7 -0
  222. package/plugins/emptyDataState/index.mjs +1 -0
  223. package/plugins/emptyDataState/ui.js +282 -0
  224. package/plugins/emptyDataState/ui.mjs +278 -0
  225. package/plugins/filters/component/value.js +16 -1
  226. package/plugins/filters/component/value.mjs +16 -1
  227. package/plugins/filters/filters.d.ts +5 -1
  228. package/plugins/filters/filters.js +22 -1
  229. package/plugins/filters/filters.mjs +22 -1
  230. package/plugins/filters/ui/multipleSelect.js +90 -79
  231. package/plugins/filters/ui/multipleSelect.mjs +90 -79
  232. package/plugins/index.d.ts +3 -0
  233. package/plugins/index.js +3 -0
  234. package/plugins/index.mjs +3 -1
  235. package/plugins/mergeCells/utils.js +1 -5
  236. package/plugins/mergeCells/utils.mjs +1 -5
  237. package/plugins/pagination/pagination.js +37 -175
  238. package/plugins/pagination/pagination.mjs +37 -175
  239. package/plugins/pagination/strategies/autoPageSize.js +2 -2
  240. package/plugins/pagination/strategies/autoPageSize.mjs +2 -2
  241. package/plugins/pagination/ui.js +6 -10
  242. package/plugins/pagination/ui.mjs +7 -11
  243. package/plugins/stretchColumns/calculator.js +3 -1
  244. package/plugins/stretchColumns/calculator.mjs +3 -1
  245. package/plugins/undoRedo/undoRedo.js +16 -6
  246. package/plugins/undoRedo/undoRedo.mjs +16 -5
  247. package/renderers/checkboxRenderer/checkboxRenderer.js +12 -15
  248. package/renderers/checkboxRenderer/checkboxRenderer.mjs +12 -15
  249. package/selection/selection.js +1 -1
  250. package/selection/selection.mjs +1 -1
  251. package/settings.d.ts +3 -0
  252. package/shortcutContexts/commands/index.js +2 -1
  253. package/shortcutContexts/commands/index.mjs +2 -1
  254. package/shortcutContexts/commands/tabNavigation.js +51 -0
  255. package/shortcutContexts/commands/tabNavigation.mjs +48 -0
  256. package/shortcutContexts/constants.js +16 -1
  257. package/shortcutContexts/constants.mjs +16 -1
  258. package/shortcutContexts/editor.js +2 -2
  259. package/shortcutContexts/editor.mjs +3 -3
  260. package/shortcutContexts/grid.js +19 -3
  261. package/shortcutContexts/grid.mjs +20 -4
  262. package/shortcuts/manager.d.ts +1 -0
  263. package/shortcuts/manager.js +17 -2
  264. package/shortcuts/manager.mjs +17 -2
  265. package/styles/handsontable.css +192 -35
  266. package/styles/handsontable.min.css +3 -3
  267. package/styles/ht-icons-horizon.css +233 -0
  268. package/styles/ht-icons-horizon.min.css +30 -0
  269. package/styles/ht-icons-main.css +233 -0
  270. package/styles/ht-icons-main.min.css +30 -0
  271. package/styles/ht-theme-classic-no-icons.css +399 -0
  272. package/styles/ht-theme-classic-no-icons.min.css +30 -0
  273. package/styles/ht-theme-classic.css +308 -556
  274. package/styles/ht-theme-classic.min.css +3 -3
  275. package/styles/ht-theme-horizon-no-icons.css +405 -0
  276. package/styles/ht-theme-horizon-no-icons.min.css +30 -0
  277. package/styles/ht-theme-horizon.css +312 -556
  278. package/styles/ht-theme-horizon.min.css +3 -3
  279. package/styles/ht-theme-main-no-icons.css +396 -0
  280. package/styles/ht-theme-main-no-icons.min.css +30 -0
  281. package/styles/ht-theme-main.css +303 -556
  282. package/styles/ht-theme-main.min.css +3 -3
  283. package/tableView.js +23 -5
  284. package/tableView.mjs +23 -5
  285. package/utils/dataStructures/uniqueMap.js +10 -0
  286. package/utils/dataStructures/uniqueMap.mjs +10 -0
  287. package/utils/ghostTable.js +0 -3
  288. package/utils/ghostTable.mjs +0 -3
  289. package/utils/stylesHandler.js +19 -4
  290. package/utils/stylesHandler.mjs +19 -4
  291. package/core/focusCatcher/index.js +0 -131
  292. package/core/focusCatcher/index.mjs +0 -127
  293. package/core/focusCatcher/utils.js +0 -31
  294. package/core/focusCatcher/utils.mjs +0 -27
  295. package/plugins/pagination/focusController.js +0 -27
  296. package/plugins/pagination/focusController.mjs +0 -23
@@ -0,0 +1,116 @@
1
+ import { normalizeCoordsIfNeeded, getMostTopStartPosition, getMostBottomEndPosition } from "../utils/utils.mjs";
2
+ import { GRID_SCOPE, GRID_GROUP, GRID_TAB_NAVIGATION_GROUP } from "../../shortcutContexts/index.mjs";
3
+ /**
4
+ * @param {Handsontable} hot The Handsontable instance.
5
+ */
6
+ export function focusGridScope(hot) {
7
+ var _hot$rootGridElement;
8
+ const clampCoordsIfNeeded = normalizeCoordsIfNeeded(hot);
9
+ const rowWrapState = {
10
+ wrapped: false,
11
+ flipped: false
12
+ };
13
+ let recentlyAddedFocusCoords;
14
+ let isSavingCoordsEnabled = true;
15
+ let isEmptyDataStateActive = false;
16
+ hot.addHook('afterSelection', () => {
17
+ if (isSavingCoordsEnabled) {
18
+ var _hot$getSelectedRange;
19
+ recentlyAddedFocusCoords = (_hot$getSelectedRange = hot.getSelectedRangeActive()) === null || _hot$getSelectedRange === void 0 ? void 0 : _hot$getSelectedRange.highlight;
20
+ }
21
+ });
22
+ hot.addHook('beforeRowWrap', (interruptedByAutoInsertMode, newCoords, isFlipped) => {
23
+ rowWrapState.wrapped = true;
24
+ rowWrapState.flipped = isFlipped;
25
+ });
26
+ hot.addHook('beforeEmptyDataStateShow', () => {
27
+ isEmptyDataStateActive = true;
28
+ });
29
+ hot.addHook('beforeEmptyDataStateHide', () => {
30
+ isEmptyDataStateActive = false;
31
+ });
32
+ const context = hot.getShortcutManager().getContext(GRID_SCOPE);
33
+ context.addShortcuts([{
34
+ keys: [['Tab'], ['Shift', 'Tab']],
35
+ preventDefault: false,
36
+ stopPropagation: false,
37
+ relativeToGroup: GRID_GROUP,
38
+ group: GRID_TAB_NAVIGATION_GROUP,
39
+ position: 'before',
40
+ callback() {
41
+ const {
42
+ tabNavigation
43
+ } = hot.getSettings();
44
+ if (hot.getSelectedRangeActive() && !tabNavigation) {
45
+ isSavingCoordsEnabled = false;
46
+ }
47
+ }
48
+ }, {
49
+ keys: [['Tab'], ['Shift', 'Tab']],
50
+ preventDefault: false,
51
+ stopPropagation: false,
52
+ relativeToGroup: GRID_GROUP,
53
+ group: GRID_TAB_NAVIGATION_GROUP,
54
+ callback(event) {
55
+ const {
56
+ tabNavigation,
57
+ autoWrapRow
58
+ } = hot.getSettings();
59
+ isSavingCoordsEnabled = true;
60
+ if (!tabNavigation || !hot.selection.isSelected() || autoWrapRow && rowWrapState.wrapped && rowWrapState.flipped || !autoWrapRow && rowWrapState.wrapped) {
61
+ if (autoWrapRow && rowWrapState.wrapped && rowWrapState.flipped) {
62
+ recentlyAddedFocusCoords = event.shiftKey ? getMostTopStartPosition(hot) : getMostBottomEndPosition(hot);
63
+ }
64
+ rowWrapState.wrapped = false;
65
+ rowWrapState.flipped = false;
66
+ }
67
+ },
68
+ position: 'after'
69
+ }]);
70
+ const container = (_hot$rootGridElement = hot.rootGridElement) !== null && _hot$rootGridElement !== void 0 ? _hot$rootGridElement : hot.rootElement;
71
+ hot.getFocusScopeManager().registerScope('grid', container, {
72
+ contains: target => {
73
+ if (container === target || container.contains(target)) {
74
+ return true;
75
+ }
76
+ if (target.closest('.htMenu') !== null) {
77
+ // TODO: Skip switching focus scope to 'grid' for context and dropdown menus since
78
+ // focus management is not implemented for them. Their focus management
79
+ // is handled manually.
80
+ return false;
81
+ }
82
+ return hot.rootPortalElement.contains(target);
83
+ },
84
+ runOnlyIf: () => {
85
+ const {
86
+ navigableHeaders
87
+ } = hot.getSettings();
88
+ if ((isEmptyDataStateActive || !navigableHeaders) && hot.countRenderedRows() === 0 && hot.countRenderedCols() === 0 && hot.countRowHeaders() > 0 && hot.countColHeaders() > 0) {
89
+ // When the corner is only rendered, and the EmptyDataState is active, deactivate the scope.
90
+ return false;
91
+ }
92
+ return !navigableHeaders && hot.countRenderedRows() > 0 && hot.countRenderedCols() > 0 || navigableHeaders && (hot.countRowHeaders() > 0 || hot.countColHeaders() > 0);
93
+ },
94
+ onActivate: focusSource => {
95
+ if (focusSource === 'tab_from_above') {
96
+ var _clampCoordsIfNeeded;
97
+ const mostTopStartCoords = (_clampCoordsIfNeeded = clampCoordsIfNeeded(recentlyAddedFocusCoords)) !== null && _clampCoordsIfNeeded !== void 0 ? _clampCoordsIfNeeded : getMostTopStartPosition(hot);
98
+ if (mostTopStartCoords) {
99
+ const result = hot.runHooks('modifyFocusOnTabNavigation', 'from_above', mostTopStartCoords);
100
+ if (result !== false) {
101
+ hot.selectCell(mostTopStartCoords.row, mostTopStartCoords.col);
102
+ }
103
+ }
104
+ } else if (focusSource === 'tab_from_below') {
105
+ var _clampCoordsIfNeeded2;
106
+ const mostBottomEndCoords = (_clampCoordsIfNeeded2 = clampCoordsIfNeeded(recentlyAddedFocusCoords)) !== null && _clampCoordsIfNeeded2 !== void 0 ? _clampCoordsIfNeeded2 : getMostBottomEndPosition(hot);
107
+ if (mostBottomEndCoords) {
108
+ const result = hot.runHooks('modifyFocusOnTabNavigation', 'from_below', mostBottomEndCoords);
109
+ if (result !== false) {
110
+ hot.selectCell(mostBottomEndCoords.row, mostBottomEndCoords.col);
111
+ }
112
+ }
113
+ }
114
+ }
115
+ });
116
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.registerAllFocusScopes = registerAllFocusScopes;
5
+ var _grid = require("./grid");
6
+ /**
7
+ * Register all focus scopes.
8
+ *
9
+ * @param {Handsontable} hotInstance The Handsontable instance.
10
+ */
11
+ function registerAllFocusScopes(hotInstance) {
12
+ [_grid.focusGridScope].forEach(scope => scope(hotInstance));
13
+ }
@@ -0,0 +1,9 @@
1
+ import { focusGridScope } from "./grid.mjs";
2
+ /**
3
+ * Register all focus scopes.
4
+ *
5
+ * @param {Handsontable} hotInstance The Handsontable instance.
6
+ */
7
+ export function registerAllFocusScopes(hotInstance) {
8
+ [focusGridScope].forEach(scope => scope(hotInstance));
9
+ }
@@ -2,63 +2,51 @@
2
2
 
3
3
  exports.__esModule = true;
4
4
  exports.installFocusDetector = installFocusDetector;
5
- var _element = require("../helpers/dom/element");
6
- var _a11y = require("../helpers/a11y");
5
+ var _element = require("../../helpers/dom/element");
6
+ var _a11y = require("../../helpers/a11y");
7
+ var _constants = require("../constants");
7
8
  /**
8
9
  * @typedef {object} FocusDetector
9
10
  * @property {function(): void} activate Activates the focus detector.
10
11
  * @property {function(): void} deactivate Deactivates the focus detector.
11
- * @property {function('from_above' | 'from_below'): void} focus Focuses the input element in the given direction.
12
+ * @property {function(): void} destroy Destroys the focus detector.
12
13
  */
13
14
  /**
14
15
  * Installs a focus detector module. The module appends two input elements into the DOM side by side.
15
16
  * When the first input is focused, then it means that a user entered to the component using the TAB key
16
17
  * from the element above. When the second input is focused, a user enters to the component from
17
- * the element below the table. Each action, once detected, triggers the specific hook.
18
+ * the element below the table.
18
19
  *
19
20
  * @param {Handsontable} hot The Handsontable instance.
20
21
  * @param {HTMLElement} wrapperElement The wrapper element to install the focus detector into.
21
- * @param {{ onFocus: Function }} hooks An object with defined callbacks to call.
22
22
  * @returns {FocusDetector}
23
23
  */
24
24
  function installFocusDetector(hot, wrapperElement) {
25
- let hooks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
26
- const inputTrapTop = createInputElement(hot);
27
- const inputTrapBottom = createInputElement(hot);
28
- inputTrapTop.addEventListener('focus', () => hooks === null || hooks === void 0 ? void 0 : hooks.onFocus('from_above'));
29
- inputTrapBottom.addEventListener('focus', () => hooks === null || hooks === void 0 ? void 0 : hooks.onFocus('from_below'));
25
+ const inputTrapTop = createInputElement(hot, _constants.FOCUS_SOURCES.TAB_FROM_ABOVE);
26
+ const inputTrapBottom = createInputElement(hot, _constants.FOCUS_SOURCES.TAB_FROM_BELOW);
30
27
  wrapperElement.prepend(inputTrapTop);
31
28
  wrapperElement.append(inputTrapBottom);
32
29
  return {
33
- /**
34
- * Focuses the input element in the given direction.
35
- *
36
- * @param {string} direction The direction to focus the input element in.
37
- */
38
- focus(direction) {
39
- if (direction === 'from_above') {
40
- inputTrapTop.focus();
41
- } else {
42
- inputTrapBottom.focus();
43
- }
44
- },
45
30
  /**
46
31
  * Activates the detector by resetting the tabIndex of the input elements.
47
32
  */
48
33
  activate() {
49
- hot._registerTimeout(() => {
50
- inputTrapTop.tabIndex = 0;
51
- inputTrapBottom.tabIndex = 0;
52
- }, 10);
34
+ inputTrapTop.tabIndex = 0;
35
+ inputTrapBottom.tabIndex = 0;
53
36
  },
54
37
  /**
55
38
  * Deactivates the detector by setting tabIndex to -1.
56
39
  */
57
40
  deactivate() {
58
- hot._registerTimeout(() => {
59
- inputTrapTop.tabIndex = -1;
60
- inputTrapBottom.tabIndex = -1;
61
- }, 10);
41
+ inputTrapTop.tabIndex = -1;
42
+ inputTrapBottom.tabIndex = -1;
43
+ },
44
+ /**
45
+ * Destroys the focus detector.
46
+ */
47
+ destroy() {
48
+ inputTrapTop.remove();
49
+ inputTrapBottom.remove();
62
50
  }
63
51
  };
64
52
  }
@@ -67,14 +55,16 @@ function installFocusDetector(hot, wrapperElement) {
67
55
  * Creates a new HTML input element.
68
56
  *
69
57
  * @param {Handsontable} hot The Handsontable instance.
58
+ * @param {'from_above' | 'from_below'} focusSource The source of the focus event.
70
59
  * @returns {HTMLInputElement}
71
60
  */
72
- function createInputElement(hot) {
61
+ function createInputElement(hot, focusSource) {
73
62
  const rootDocument = hot.rootDocument;
74
63
  const input = rootDocument.createElement('input');
75
64
  input.type = 'text';
76
65
  input.name = 'htFocusCatcher';
77
66
  input.classList.add('htFocusCatcher');
67
+ input.dataset.htFocusSource = focusSource;
78
68
  if (hot.getSettings().ariaTags) {
79
69
  (0, _element.setAttribute)(input, [(0, _a11y.A11Y_LABEL)('Focus catcher')]);
80
70
  }
@@ -1,60 +1,48 @@
1
- import { setAttribute } from "../helpers/dom/element.mjs";
2
- import { A11Y_LABEL } from "../helpers/a11y.mjs";
1
+ import { setAttribute } from "../../helpers/dom/element.mjs";
2
+ import { A11Y_LABEL } from "../../helpers/a11y.mjs";
3
+ import { FOCUS_SOURCES } from "../constants.mjs";
3
4
  /**
4
5
  * @typedef {object} FocusDetector
5
6
  * @property {function(): void} activate Activates the focus detector.
6
7
  * @property {function(): void} deactivate Deactivates the focus detector.
7
- * @property {function('from_above' | 'from_below'): void} focus Focuses the input element in the given direction.
8
+ * @property {function(): void} destroy Destroys the focus detector.
8
9
  */
9
10
  /**
10
11
  * Installs a focus detector module. The module appends two input elements into the DOM side by side.
11
12
  * When the first input is focused, then it means that a user entered to the component using the TAB key
12
13
  * from the element above. When the second input is focused, a user enters to the component from
13
- * the element below the table. Each action, once detected, triggers the specific hook.
14
+ * the element below the table.
14
15
  *
15
16
  * @param {Handsontable} hot The Handsontable instance.
16
17
  * @param {HTMLElement} wrapperElement The wrapper element to install the focus detector into.
17
- * @param {{ onFocus: Function }} hooks An object with defined callbacks to call.
18
18
  * @returns {FocusDetector}
19
19
  */
20
20
  export function installFocusDetector(hot, wrapperElement) {
21
- let hooks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
22
- const inputTrapTop = createInputElement(hot);
23
- const inputTrapBottom = createInputElement(hot);
24
- inputTrapTop.addEventListener('focus', () => hooks === null || hooks === void 0 ? void 0 : hooks.onFocus('from_above'));
25
- inputTrapBottom.addEventListener('focus', () => hooks === null || hooks === void 0 ? void 0 : hooks.onFocus('from_below'));
21
+ const inputTrapTop = createInputElement(hot, FOCUS_SOURCES.TAB_FROM_ABOVE);
22
+ const inputTrapBottom = createInputElement(hot, FOCUS_SOURCES.TAB_FROM_BELOW);
26
23
  wrapperElement.prepend(inputTrapTop);
27
24
  wrapperElement.append(inputTrapBottom);
28
25
  return {
29
- /**
30
- * Focuses the input element in the given direction.
31
- *
32
- * @param {string} direction The direction to focus the input element in.
33
- */
34
- focus(direction) {
35
- if (direction === 'from_above') {
36
- inputTrapTop.focus();
37
- } else {
38
- inputTrapBottom.focus();
39
- }
40
- },
41
26
  /**
42
27
  * Activates the detector by resetting the tabIndex of the input elements.
43
28
  */
44
29
  activate() {
45
- hot._registerTimeout(() => {
46
- inputTrapTop.tabIndex = 0;
47
- inputTrapBottom.tabIndex = 0;
48
- }, 10);
30
+ inputTrapTop.tabIndex = 0;
31
+ inputTrapBottom.tabIndex = 0;
49
32
  },
50
33
  /**
51
34
  * Deactivates the detector by setting tabIndex to -1.
52
35
  */
53
36
  deactivate() {
54
- hot._registerTimeout(() => {
55
- inputTrapTop.tabIndex = -1;
56
- inputTrapBottom.tabIndex = -1;
57
- }, 10);
37
+ inputTrapTop.tabIndex = -1;
38
+ inputTrapBottom.tabIndex = -1;
39
+ },
40
+ /**
41
+ * Destroys the focus detector.
42
+ */
43
+ destroy() {
44
+ inputTrapTop.remove();
45
+ inputTrapBottom.remove();
58
46
  }
59
47
  };
60
48
  }
@@ -63,14 +51,16 @@ export function installFocusDetector(hot, wrapperElement) {
63
51
  * Creates a new HTML input element.
64
52
  *
65
53
  * @param {Handsontable} hot The Handsontable instance.
54
+ * @param {'from_above' | 'from_below'} focusSource The source of the focus event.
66
55
  * @returns {HTMLInputElement}
67
56
  */
68
- function createInputElement(hot) {
57
+ function createInputElement(hot, focusSource) {
69
58
  const rootDocument = hot.rootDocument;
70
59
  const input = rootDocument.createElement('input');
71
60
  input.type = 'text';
72
61
  input.name = 'htFocusCatcher';
73
62
  input.classList.add('htFocusCatcher');
63
+ input.dataset.htFocusSource = focusSource;
74
64
  if (hot.getSettings().ariaTags) {
75
65
  setAttribute(input, [A11Y_LABEL('Focus catcher')]);
76
66
  }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.getMostBottomEndPosition = getMostBottomEndPosition;
5
+ exports.getMostTopStartPosition = getMostTopStartPosition;
6
+ exports.normalizeCoordsIfNeeded = normalizeCoordsIfNeeded;
7
+ var _number = require("../../helpers/number");
8
+ /**
9
+ * Normalizes the coordinates (clamps to nearest visible cell position within dataset range).
10
+ *
11
+ * @param {Core} hot The Handsontable instance.
12
+ * @returns {function(Coords | undefined): Coords | null}
13
+ */
14
+ function normalizeCoordsIfNeeded(hot) {
15
+ return coords => {
16
+ if (!coords) {
17
+ return null;
18
+ }
19
+ const {
20
+ rowIndexMapper,
21
+ columnIndexMapper
22
+ } = hot;
23
+ if (rowIndexMapper.isHidden(coords.row) || columnIndexMapper.isHidden(coords.col)) {
24
+ return null;
25
+ }
26
+ const mostTopStartCoords = getMostTopStartPosition(hot);
27
+ const mostBottomEndCoords = getMostBottomEndPosition(hot);
28
+ if (mostTopStartCoords === null || mostBottomEndCoords === null) {
29
+ return null;
30
+ }
31
+ coords.row = (0, _number.clamp)(coords.row, mostTopStartCoords.row, mostBottomEndCoords.row);
32
+ coords.col = (0, _number.clamp)(coords.col, mostTopStartCoords.col, mostBottomEndCoords.col);
33
+ return coords;
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Gets the coordinates of the most top-start cell or header (depends on the table settings and its size).
39
+ *
40
+ * @param {Core} hot The Handsontable instance.
41
+ * @returns {CellCoords|null}
42
+ */
43
+ function getMostTopStartPosition(hot) {
44
+ const {
45
+ rowIndexMapper,
46
+ columnIndexMapper
47
+ } = hot;
48
+ const {
49
+ navigableHeaders
50
+ } = hot.getSettings();
51
+ let topRow = navigableHeaders && hot.countColHeaders() > 0 ? -hot.countColHeaders() : 0;
52
+ let startColumn = navigableHeaders && hot.countRowHeaders() > 0 ? -hot.countRowHeaders() : 0;
53
+ if (topRow === 0) {
54
+ topRow = rowIndexMapper.getVisualFromRenderableIndex(topRow);
55
+ }
56
+ if (startColumn === 0) {
57
+ startColumn = columnIndexMapper.getVisualFromRenderableIndex(startColumn);
58
+ }
59
+ if (topRow === null || startColumn === null) {
60
+ return null;
61
+ }
62
+ return hot._createCellCoords(topRow, startColumn);
63
+ }
64
+
65
+ /**
66
+ * Gets the coordinates of the most bottom-end cell or header (depends on the table settings and its size).
67
+ *
68
+ * @param {Core} hot The Handsontable instance.
69
+ * @returns {CellCoords|null}
70
+ */
71
+ function getMostBottomEndPosition(hot) {
72
+ var _rowIndexMapper$getVi, _columnIndexMapper$ge;
73
+ const {
74
+ rowIndexMapper,
75
+ columnIndexMapper
76
+ } = hot;
77
+ const {
78
+ navigableHeaders
79
+ } = hot.getSettings();
80
+ let bottomRow = rowIndexMapper.getRenderableIndexesLength() - 1;
81
+ let endColumn = columnIndexMapper.getRenderableIndexesLength() - 1;
82
+ if (bottomRow < 0) {
83
+ if (!navigableHeaders || hot.countColHeaders() === 0) {
84
+ return null;
85
+ }
86
+ bottomRow = -1;
87
+ }
88
+ if (endColumn < 0) {
89
+ if (!navigableHeaders || hot.countColHeaders() === 0) {
90
+ return null;
91
+ }
92
+ endColumn = -1;
93
+ }
94
+ return hot._createCellCoords((_rowIndexMapper$getVi = rowIndexMapper.getVisualFromRenderableIndex(bottomRow)) !== null && _rowIndexMapper$getVi !== void 0 ? _rowIndexMapper$getVi : bottomRow, (_columnIndexMapper$ge = columnIndexMapper.getVisualFromRenderableIndex(endColumn)) !== null && _columnIndexMapper$ge !== void 0 ? _columnIndexMapper$ge : endColumn);
95
+ }
@@ -0,0 +1,89 @@
1
+ import { clamp } from "../../helpers/number.mjs";
2
+ /**
3
+ * Normalizes the coordinates (clamps to nearest visible cell position within dataset range).
4
+ *
5
+ * @param {Core} hot The Handsontable instance.
6
+ * @returns {function(Coords | undefined): Coords | null}
7
+ */
8
+ export function normalizeCoordsIfNeeded(hot) {
9
+ return coords => {
10
+ if (!coords) {
11
+ return null;
12
+ }
13
+ const {
14
+ rowIndexMapper,
15
+ columnIndexMapper
16
+ } = hot;
17
+ if (rowIndexMapper.isHidden(coords.row) || columnIndexMapper.isHidden(coords.col)) {
18
+ return null;
19
+ }
20
+ const mostTopStartCoords = getMostTopStartPosition(hot);
21
+ const mostBottomEndCoords = getMostBottomEndPosition(hot);
22
+ if (mostTopStartCoords === null || mostBottomEndCoords === null) {
23
+ return null;
24
+ }
25
+ coords.row = clamp(coords.row, mostTopStartCoords.row, mostBottomEndCoords.row);
26
+ coords.col = clamp(coords.col, mostTopStartCoords.col, mostBottomEndCoords.col);
27
+ return coords;
28
+ };
29
+ }
30
+
31
+ /**
32
+ * Gets the coordinates of the most top-start cell or header (depends on the table settings and its size).
33
+ *
34
+ * @param {Core} hot The Handsontable instance.
35
+ * @returns {CellCoords|null}
36
+ */
37
+ export function getMostTopStartPosition(hot) {
38
+ const {
39
+ rowIndexMapper,
40
+ columnIndexMapper
41
+ } = hot;
42
+ const {
43
+ navigableHeaders
44
+ } = hot.getSettings();
45
+ let topRow = navigableHeaders && hot.countColHeaders() > 0 ? -hot.countColHeaders() : 0;
46
+ let startColumn = navigableHeaders && hot.countRowHeaders() > 0 ? -hot.countRowHeaders() : 0;
47
+ if (topRow === 0) {
48
+ topRow = rowIndexMapper.getVisualFromRenderableIndex(topRow);
49
+ }
50
+ if (startColumn === 0) {
51
+ startColumn = columnIndexMapper.getVisualFromRenderableIndex(startColumn);
52
+ }
53
+ if (topRow === null || startColumn === null) {
54
+ return null;
55
+ }
56
+ return hot._createCellCoords(topRow, startColumn);
57
+ }
58
+
59
+ /**
60
+ * Gets the coordinates of the most bottom-end cell or header (depends on the table settings and its size).
61
+ *
62
+ * @param {Core} hot The Handsontable instance.
63
+ * @returns {CellCoords|null}
64
+ */
65
+ export function getMostBottomEndPosition(hot) {
66
+ var _rowIndexMapper$getVi, _columnIndexMapper$ge;
67
+ const {
68
+ rowIndexMapper,
69
+ columnIndexMapper
70
+ } = hot;
71
+ const {
72
+ navigableHeaders
73
+ } = hot.getSettings();
74
+ let bottomRow = rowIndexMapper.getRenderableIndexesLength() - 1;
75
+ let endColumn = columnIndexMapper.getRenderableIndexesLength() - 1;
76
+ if (bottomRow < 0) {
77
+ if (!navigableHeaders || hot.countColHeaders() === 0) {
78
+ return null;
79
+ }
80
+ bottomRow = -1;
81
+ }
82
+ if (endColumn < 0) {
83
+ if (!navigableHeaders || hot.countColHeaders() === 0) {
84
+ return null;
85
+ }
86
+ endColumn = -1;
87
+ }
88
+ return hot._createCellCoords((_rowIndexMapper$getVi = rowIndexMapper.getVisualFromRenderableIndex(bottomRow)) !== null && _rowIndexMapper$getVi !== void 0 ? _rowIndexMapper$getVi : bottomRow, (_columnIndexMapper$ge = columnIndexMapper.getVisualFromRenderableIndex(endColumn)) !== null && _columnIndexMapper$ge !== void 0 ? _columnIndexMapper$ge : endColumn);
89
+ }
@@ -1009,7 +1009,7 @@ function walkontableCalculateScrollbarWidth() {
1009
1009
  const outer = rootDocument.createElement('div');
1010
1010
 
1011
1011
  // Fix for Safari custom scrollbar size
1012
- if ((0, _browser.isSafari)() && !(0, _browser.isMobileBrowser)()) {
1012
+ if ((0, _browser.isSafari)() && !(0, _browser.isMobileBrowser)() && !(0, _browser.isIpadOS)()) {
1013
1013
  outer.classList.add('htScrollbarSafariTest');
1014
1014
  }
1015
1015
  outer.style.boxSizing = 'content-box';
@@ -5,7 +5,7 @@ import "core-js/modules/esnext.iterator.filter.js";
5
5
  import "core-js/modules/esnext.iterator.for-each.js";
6
6
  import { sanitize } from "../string.mjs";
7
7
  import { A11Y_HIDDEN } from "../a11y.mjs";
8
- import { isWindowsOS, isSafari, isMobileBrowser } from "../browser.mjs";
8
+ import { isWindowsOS, isSafari, isMobileBrowser, isIpadOS } from "../browser.mjs";
9
9
  /**
10
10
  * Get the parent of the specified node in the DOM tree.
11
11
  *
@@ -946,7 +946,7 @@ function walkontableCalculateScrollbarWidth() {
946
946
  const outer = rootDocument.createElement('div');
947
947
 
948
948
  // Fix for Safari custom scrollbar size
949
- if (isSafari() && !isMobileBrowser()) {
949
+ if (isSafari() && !isMobileBrowser() && !isIpadOS()) {
950
950
  outer.classList.add('htScrollbarSafariTest');
951
951
  }
952
952
  outer.style.boxSizing = 'content-box';
@@ -55,7 +55,7 @@ function isLeftClick(event) {
55
55
  * @returns {boolean}
56
56
  */
57
57
  function isTouchEvent(event) {
58
- return event instanceof TouchEvent;
58
+ return typeof TouchEvent !== 'undefined' && event instanceof TouchEvent;
59
59
  }
60
60
 
61
61
  /**
@@ -46,7 +46,7 @@ export function isLeftClick(event) {
46
46
  * @returns {boolean}
47
47
  */
48
48
  export function isTouchEvent(event) {
49
- return event instanceof TouchEvent;
49
+ return typeof TouchEvent !== 'undefined' && event instanceof TouchEvent;
50
50
  }
51
51
 
52
52
  /**
package/helpers/mixed.js CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  exports.__esModule = true;
4
4
  exports._injectProductInfo = _injectProductInfo;
5
- exports.getMostBottomEndPosition = getMostBottomEndPosition;
6
- exports.getMostTopStartPosition = getMostTopStartPosition;
7
5
  exports.isDefined = isDefined;
8
6
  exports.isEmpty = isEmpty;
9
7
  exports.isRegExp = isRegExp;
@@ -136,7 +134,7 @@ const domMessages = {
136
134
  function _injectProductInfo(key, element) {
137
135
  const hasValidType = !isEmpty(key);
138
136
  const isNonCommercial = typeof key === 'string' && key.toLowerCase() === 'non-commercial-and-evaluation';
139
- const hotVersion = "16.1.1";
137
+ const hotVersion = "16.2.0-next-90d1117-20251117";
140
138
  let keyValidityDate;
141
139
  let consoleMessageState = 'invalid';
142
140
  let domMessageState = 'invalid';
@@ -144,7 +142,7 @@ function _injectProductInfo(key, element) {
144
142
  const schemaValidity = _checkKeySchema(key);
145
143
  if (hasValidType || isNonCommercial || schemaValidity) {
146
144
  if (schemaValidity) {
147
- const releaseDate = (0, _moment.default)("23/09/2025", 'DD/MM/YYYY');
145
+ const releaseDate = (0, _moment.default)("20/11/2025", 'DD/MM/YYYY');
148
146
  const releaseDays = Math.floor(releaseDate.toDate().getTime() / 8.64e7);
149
147
  const keyValidityDays = _extractTime(key);
150
148
  keyValidityDate = (0, _moment.default)((keyValidityDays + 1) * 8.64e7, 'x').format('MMMM DD, YYYY');
@@ -210,65 +208,4 @@ function _checkKeySchema(v) {
210
208
  }
211
209
  return p === z;
212
210
  }
213
-
214
- /**
215
- * Gets the coordinates of the most top-start cell or header (depends on the table settings and its size).
216
- *
217
- * @param {Core} hot The Handsontable instance.
218
- * @returns {CellCoords|null}
219
- */
220
- function getMostTopStartPosition(hot) {
221
- const {
222
- rowIndexMapper,
223
- columnIndexMapper
224
- } = hot;
225
- const {
226
- navigableHeaders
227
- } = hot.getSettings();
228
- let topRow = navigableHeaders && hot.countColHeaders() > 0 ? -hot.countColHeaders() : 0;
229
- let startColumn = navigableHeaders && hot.countRowHeaders() > 0 ? -hot.countRowHeaders() : 0;
230
- if (topRow === 0) {
231
- topRow = rowIndexMapper.getVisualFromRenderableIndex(topRow);
232
- }
233
- if (startColumn === 0) {
234
- startColumn = columnIndexMapper.getVisualFromRenderableIndex(startColumn);
235
- }
236
- if (topRow === null || startColumn === null) {
237
- return null;
238
- }
239
- return hot._createCellCoords(topRow, startColumn);
240
- }
241
-
242
- /**
243
- * Gets the coordinates of the most bottom-end cell or header (depends on the table settings and its size).
244
- *
245
- * @param {Core} hot The Handsontable instance.
246
- * @returns {CellCoords|null}
247
- */
248
- function getMostBottomEndPosition(hot) {
249
- var _rowIndexMapper$getVi, _columnIndexMapper$ge;
250
- const {
251
- rowIndexMapper,
252
- columnIndexMapper
253
- } = hot;
254
- const {
255
- navigableHeaders
256
- } = hot.getSettings();
257
- let bottomRow = rowIndexMapper.getRenderableIndexesLength() - 1;
258
- let endColumn = columnIndexMapper.getRenderableIndexesLength() - 1;
259
- if (bottomRow < 0) {
260
- if (!navigableHeaders || hot.countColHeaders() === 0) {
261
- return null;
262
- }
263
- bottomRow = -1;
264
- }
265
- if (endColumn < 0) {
266
- if (!navigableHeaders || hot.countColHeaders() === 0) {
267
- return null;
268
- }
269
- endColumn = -1;
270
- }
271
- return hot._createCellCoords((_rowIndexMapper$getVi = rowIndexMapper.getVisualFromRenderableIndex(bottomRow)) !== null && _rowIndexMapper$getVi !== void 0 ? _rowIndexMapper$getVi : bottomRow, (_columnIndexMapper$ge = columnIndexMapper.getVisualFromRenderableIndex(endColumn)) !== null && _columnIndexMapper$ge !== void 0 ? _columnIndexMapper$ge : endColumn);
272
- }
273
-
274
211
  /* eslint-enable */