handsontable 14.5.0 → 14.6.0-next-6fbf568-20240930

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 (124) hide show
  1. package/3rdparty/walkontable/src/renderer/rows.js +10 -0
  2. package/3rdparty/walkontable/src/renderer/rows.mjs +11 -1
  3. package/3rdparty/walkontable/src/selection/manager.js +7 -7
  4. package/3rdparty/walkontable/src/selection/manager.mjs +7 -7
  5. package/3rdparty/walkontable/src/selection/scanner.js +7 -7
  6. package/3rdparty/walkontable/src/selection/scanner.mjs +7 -7
  7. package/CHANGELOG.md +29 -0
  8. package/base.js +2 -2
  9. package/base.mjs +2 -2
  10. package/core.d.ts +13 -2
  11. package/core.js +160 -9
  12. package/core.mjs +160 -9
  13. package/dataMap/metaManager/lazyFactoryMap.js +7 -7
  14. package/dataMap/metaManager/lazyFactoryMap.mjs +7 -7
  15. package/dataMap/metaManager/metaSchema.js +5 -6
  16. package/dataMap/metaManager/metaSchema.mjs +7 -8
  17. package/dataMap/metaManager/mods/dynamicCellMeta.js +7 -7
  18. package/dataMap/metaManager/mods/dynamicCellMeta.mjs +7 -7
  19. package/dataMap/metaManager/mods/extendMetaProperties.js +7 -7
  20. package/dataMap/metaManager/mods/extendMetaProperties.mjs +7 -7
  21. package/dataMap/metaManager/utils.js +7 -7
  22. package/dataMap/metaManager/utils.mjs +7 -7
  23. package/dist/handsontable.css +3 -17
  24. package/dist/handsontable.full.css +3 -17
  25. package/dist/handsontable.full.js +3501 -3220
  26. package/dist/handsontable.full.min.css +3 -3
  27. package/dist/handsontable.full.min.js +109 -119
  28. package/dist/handsontable.js +3175 -2898
  29. package/dist/handsontable.min.css +3 -3
  30. package/dist/handsontable.min.js +19 -19
  31. package/editors/autocompleteEditor/autocompleteEditor.d.ts +1 -1
  32. package/helpers/a11y.js +2 -0
  33. package/helpers/a11y.mjs +1 -0
  34. package/helpers/array.js +7 -7
  35. package/helpers/array.mjs +7 -7
  36. package/helpers/mixed.js +2 -2
  37. package/helpers/mixed.mjs +2 -2
  38. package/helpers/number.js +7 -7
  39. package/helpers/number.mjs +7 -7
  40. package/package.json +1 -1
  41. package/pluginHooks.d.ts +1 -1
  42. package/pluginHooks.js +4 -1
  43. package/pluginHooks.mjs +4 -1
  44. package/plugins/autoRowSize/autoRowSize.js +1 -2
  45. package/plugins/autoRowSize/autoRowSize.mjs +1 -2
  46. package/plugins/columnSorting/columnSorting.js +10 -1
  47. package/plugins/columnSorting/columnSorting.mjs +10 -1
  48. package/plugins/columnSorting/utils.js +7 -7
  49. package/plugins/columnSorting/utils.mjs +7 -7
  50. package/plugins/contextMenu/contextMenu.js +7 -0
  51. package/plugins/contextMenu/contextMenu.mjs +7 -0
  52. package/plugins/contextMenu/menu/menu.js +47 -14
  53. package/plugins/contextMenu/menu/menu.mjs +48 -15
  54. package/plugins/contextMenu/menu/menuItemRenderer.js +3 -4
  55. package/plugins/contextMenu/menu/menuItemRenderer.mjs +5 -6
  56. package/plugins/contextMenu/menu/positioner.js +4 -12
  57. package/plugins/contextMenu/menu/positioner.mjs +4 -12
  58. package/plugins/contextMenu/menu/utils.js +11 -0
  59. package/plugins/contextMenu/menu/utils.mjs +10 -0
  60. package/plugins/contextMenu/predefinedItems/alignment.js +56 -49
  61. package/plugins/contextMenu/predefinedItems/alignment.mjs +57 -50
  62. package/plugins/contextMenu/predefinedItems/readOnly.js +8 -0
  63. package/plugins/contextMenu/predefinedItems/readOnly.mjs +8 -0
  64. package/plugins/contextMenu/utils.js +26 -0
  65. package/plugins/contextMenu/utils.mjs +24 -0
  66. package/plugins/copyPaste/copyPaste.js +14 -14
  67. package/plugins/copyPaste/copyPaste.mjs +14 -14
  68. package/plugins/dropdownMenu/dropdownMenu.js +10 -4
  69. package/plugins/dropdownMenu/dropdownMenu.mjs +10 -4
  70. package/plugins/filters/component/condition.js +6 -1
  71. package/plugins/filters/component/condition.mjs +6 -1
  72. package/plugins/filters/component/value.js +6 -1
  73. package/plugins/filters/component/value.mjs +6 -1
  74. package/plugins/filters/conditionCollection.d.ts +4 -3
  75. package/plugins/filters/conditionCollection.js +26 -0
  76. package/plugins/filters/conditionCollection.mjs +26 -0
  77. package/plugins/filters/filters.js +4 -1
  78. package/plugins/filters/filters.mjs +4 -1
  79. package/plugins/filters/ui/multipleSelect.js +7 -9
  80. package/plugins/filters/ui/multipleSelect.mjs +7 -9
  81. package/plugins/filters/utils.js +7 -7
  82. package/plugins/filters/utils.mjs +7 -7
  83. package/plugins/formulas/formulas.js +7 -7
  84. package/plugins/formulas/formulas.mjs +7 -7
  85. package/plugins/hiddenColumns/hiddenColumns.js +7 -7
  86. package/plugins/hiddenColumns/hiddenColumns.mjs +7 -7
  87. package/plugins/hiddenRows/hiddenRows.js +7 -7
  88. package/plugins/hiddenRows/hiddenRows.mjs +7 -7
  89. package/plugins/mergeCells/cellsCollection.js +18 -16
  90. package/plugins/mergeCells/cellsCollection.mjs +19 -17
  91. package/plugins/mergeCells/mergeCells.js +7 -7
  92. package/plugins/mergeCells/mergeCells.mjs +7 -7
  93. package/plugins/nestedHeaders/stateManager/nodeModifiers/collapse.js +7 -7
  94. package/plugins/nestedHeaders/stateManager/nodeModifiers/collapse.mjs +7 -7
  95. package/plugins/nestedHeaders/stateManager/nodeModifiers/expand.js +7 -7
  96. package/plugins/nestedHeaders/stateManager/nodeModifiers/expand.mjs +7 -7
  97. package/plugins/nestedRows/nestedRows.js +7 -7
  98. package/plugins/nestedRows/nestedRows.mjs +7 -7
  99. package/plugins/trimRows/trimRows.js +7 -7
  100. package/plugins/trimRows/trimRows.mjs +7 -7
  101. package/plugins/undoRedo/undoRedo.js +9 -5
  102. package/plugins/undoRedo/undoRedo.mjs +9 -5
  103. package/renderers/checkboxRenderer/checkboxRenderer.js +18 -6
  104. package/renderers/checkboxRenderer/checkboxRenderer.mjs +18 -6
  105. package/selection/selection.js +7 -7
  106. package/selection/selection.mjs +7 -7
  107. package/selection/utils.js +7 -7
  108. package/selection/utils.mjs +7 -7
  109. package/shortcutContexts/grid.js +10 -3
  110. package/shortcutContexts/grid.mjs +10 -3
  111. package/shortcuts/keyObserver.js +7 -7
  112. package/shortcuts/keyObserver.mjs +7 -7
  113. package/shortcuts/utils.js +3 -1
  114. package/shortcuts/utils.mjs +3 -1
  115. package/translations/changesObservable/observable.js +7 -7
  116. package/translations/changesObservable/observable.mjs +7 -7
  117. package/translations/indexMapper.js +7 -7
  118. package/translations/indexMapper.mjs +7 -7
  119. package/utils/dataStructures/uniqueSet.js +7 -7
  120. package/utils/dataStructures/uniqueSet.mjs +7 -7
  121. package/utils/ghostTable.js +11 -9
  122. package/utils/ghostTable.mjs +12 -10
  123. package/utils/paginator.js +7 -7
  124. package/utils/paginator.mjs +7 -7
@@ -17,7 +17,7 @@ export class AutocompleteEditor extends HandsontableEditor {
17
17
  limitDropdownIfNeeded(spaceAvailable: number, dropdownHeight: number): void;
18
18
  flipDropdown(dropdownHeight: number): void;
19
19
  unflipDropdown(): void;
20
- updateDropdownHeight(): void;
20
+ updateDropdownDimensions(): void;
21
21
  setDropdownHeight(height: number): void;
22
22
  highlightBestMatchingChoice(index?: number): void;
23
23
  getDropdownHeight(): number;
package/helpers/a11y.js CHANGED
@@ -21,6 +21,8 @@ const A11Y_MENU = () => ['role', 'menu'];
21
21
  exports.A11Y_MENU = A11Y_MENU;
22
22
  const A11Y_MENU_ITEM = () => ['role', 'menuitem'];
23
23
  exports.A11Y_MENU_ITEM = A11Y_MENU_ITEM;
24
+ const A11Y_MENU_ITEM_CHECKBOX = () => ['role', 'menuitemcheckbox'];
25
+ exports.A11Y_MENU_ITEM_CHECKBOX = A11Y_MENU_ITEM_CHECKBOX;
24
26
  const A11Y_COMBOBOX = () => ['role', 'combobox'];
25
27
  exports.A11Y_COMBOBOX = A11Y_COMBOBOX;
26
28
  const A11Y_LISTBOX = () => ['role', 'listbox'];
package/helpers/a11y.mjs CHANGED
@@ -8,6 +8,7 @@ export const A11Y_COLUMNHEADER = () => ['role', 'columnheader'];
8
8
  export const A11Y_ROW = () => ['role', 'row'];
9
9
  export const A11Y_MENU = () => ['role', 'menu'];
10
10
  export const A11Y_MENU_ITEM = () => ['role', 'menuitem'];
11
+ export const A11Y_MENU_ITEM_CHECKBOX = () => ['role', 'menuitemcheckbox'];
11
12
  export const A11Y_COMBOBOX = () => ['role', 'combobox'];
12
13
  export const A11Y_LISTBOX = () => ['role', 'listbox'];
13
14
  export const A11Y_OPTION = () => ['role', 'option'];
package/helpers/array.js CHANGED
@@ -19,13 +19,13 @@ exports.pivot = pivot;
19
19
  exports.stringToArray = stringToArray;
20
20
  exports.to2dArray = to2dArray;
21
21
  require("core-js/modules/es.array.push.js");
22
- require("core-js/modules/esnext.set.difference.v2.js");
23
- require("core-js/modules/esnext.set.intersection.v2.js");
24
- require("core-js/modules/esnext.set.is-disjoint-from.v2.js");
25
- require("core-js/modules/esnext.set.is-subset-of.v2.js");
26
- require("core-js/modules/esnext.set.is-superset-of.v2.js");
27
- require("core-js/modules/esnext.set.symmetric-difference.v2.js");
28
- require("core-js/modules/esnext.set.union.v2.js");
22
+ require("core-js/modules/es.set.difference.v2.js");
23
+ require("core-js/modules/es.set.intersection.v2.js");
24
+ require("core-js/modules/es.set.is-disjoint-from.v2.js");
25
+ require("core-js/modules/es.set.is-subset-of.v2.js");
26
+ require("core-js/modules/es.set.is-superset-of.v2.js");
27
+ require("core-js/modules/es.set.symmetric-difference.v2.js");
28
+ require("core-js/modules/es.set.union.v2.js");
29
29
  /**
30
30
  * @param {Array} arr An array to process.
31
31
  */
package/helpers/array.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  import "core-js/modules/es.array.push.js";
2
- import "core-js/modules/esnext.set.difference.v2.js";
3
- import "core-js/modules/esnext.set.intersection.v2.js";
4
- import "core-js/modules/esnext.set.is-disjoint-from.v2.js";
5
- import "core-js/modules/esnext.set.is-subset-of.v2.js";
6
- import "core-js/modules/esnext.set.is-superset-of.v2.js";
7
- import "core-js/modules/esnext.set.symmetric-difference.v2.js";
8
- import "core-js/modules/esnext.set.union.v2.js";
2
+ import "core-js/modules/es.set.difference.v2.js";
3
+ import "core-js/modules/es.set.intersection.v2.js";
4
+ import "core-js/modules/es.set.is-disjoint-from.v2.js";
5
+ import "core-js/modules/es.set.is-subset-of.v2.js";
6
+ import "core-js/modules/es.set.is-superset-of.v2.js";
7
+ import "core-js/modules/es.set.symmetric-difference.v2.js";
8
+ import "core-js/modules/es.set.union.v2.js";
9
9
  /**
10
10
  * @param {Array} arr An array to process.
11
11
  */
package/helpers/mixed.js CHANGED
@@ -134,7 +134,7 @@ const domMessages = {
134
134
  function _injectProductInfo(key, element) {
135
135
  const hasValidType = !isEmpty(key);
136
136
  const isNonCommercial = typeof key === 'string' && key.toLowerCase() === 'non-commercial-and-evaluation';
137
- const hotVersion = "14.5.0";
137
+ const hotVersion = "14.6.0-next-6fbf568-20240930";
138
138
  let keyValidityDate;
139
139
  let consoleMessageState = 'invalid';
140
140
  let domMessageState = 'invalid';
@@ -142,7 +142,7 @@ function _injectProductInfo(key, element) {
142
142
  const schemaValidity = _checkKeySchema(key);
143
143
  if (hasValidType || isNonCommercial || schemaValidity) {
144
144
  if (schemaValidity) {
145
- const releaseDate = (0, _moment.default)("30/07/2024", 'DD/MM/YYYY');
145
+ const releaseDate = (0, _moment.default)("01/10/2024", 'DD/MM/YYYY');
146
146
  const releaseDays = Math.floor(releaseDate.toDate().getTime() / 8.64e7);
147
147
  const keyValidityDays = _extractTime(key);
148
148
  keyValidityDate = (0, _moment.default)((keyValidityDays + 1) * 8.64e7, 'x').format('MMMM DD, YYYY');
package/helpers/mixed.mjs CHANGED
@@ -124,7 +124,7 @@ const domMessages = {
124
124
  export function _injectProductInfo(key, element) {
125
125
  const hasValidType = !isEmpty(key);
126
126
  const isNonCommercial = typeof key === 'string' && key.toLowerCase() === 'non-commercial-and-evaluation';
127
- const hotVersion = "14.5.0";
127
+ const hotVersion = "14.6.0-next-6fbf568-20240930";
128
128
  let keyValidityDate;
129
129
  let consoleMessageState = 'invalid';
130
130
  let domMessageState = 'invalid';
@@ -132,7 +132,7 @@ export function _injectProductInfo(key, element) {
132
132
  const schemaValidity = _checkKeySchema(key);
133
133
  if (hasValidType || isNonCommercial || schemaValidity) {
134
134
  if (schemaValidity) {
135
- const releaseDate = moment("30/07/2024", 'DD/MM/YYYY');
135
+ const releaseDate = moment("01/10/2024", 'DD/MM/YYYY');
136
136
  const releaseDays = Math.floor(releaseDate.toDate().getTime() / 8.64e7);
137
137
  const keyValidityDays = _extractTime(key);
138
138
  keyValidityDate = moment((keyValidityDays + 1) * 8.64e7, 'x').format('MMMM DD, YYYY');
package/helpers/number.js CHANGED
@@ -7,13 +7,13 @@ exports.isNumericLike = isNumericLike;
7
7
  exports.rangeEach = rangeEach;
8
8
  exports.rangeEachReverse = rangeEachReverse;
9
9
  exports.valueAccordingPercent = valueAccordingPercent;
10
- require("core-js/modules/esnext.set.difference.v2.js");
11
- require("core-js/modules/esnext.set.intersection.v2.js");
12
- require("core-js/modules/esnext.set.is-disjoint-from.v2.js");
13
- require("core-js/modules/esnext.set.is-subset-of.v2.js");
14
- require("core-js/modules/esnext.set.is-superset-of.v2.js");
15
- require("core-js/modules/esnext.set.symmetric-difference.v2.js");
16
- require("core-js/modules/esnext.set.union.v2.js");
10
+ require("core-js/modules/es.set.difference.v2.js");
11
+ require("core-js/modules/es.set.intersection.v2.js");
12
+ require("core-js/modules/es.set.is-disjoint-from.v2.js");
13
+ require("core-js/modules/es.set.is-subset-of.v2.js");
14
+ require("core-js/modules/es.set.is-superset-of.v2.js");
15
+ require("core-js/modules/es.set.symmetric-difference.v2.js");
16
+ require("core-js/modules/es.set.union.v2.js");
17
17
  /* eslint-disable jsdoc/require-description-complete-sentence */
18
18
  /**
19
19
  * Checks if the passed value is numeric one. For example these values (passed as string or number)
@@ -1,10 +1,10 @@
1
- import "core-js/modules/esnext.set.difference.v2.js";
2
- import "core-js/modules/esnext.set.intersection.v2.js";
3
- import "core-js/modules/esnext.set.is-disjoint-from.v2.js";
4
- import "core-js/modules/esnext.set.is-subset-of.v2.js";
5
- import "core-js/modules/esnext.set.is-superset-of.v2.js";
6
- import "core-js/modules/esnext.set.symmetric-difference.v2.js";
7
- import "core-js/modules/esnext.set.union.v2.js";
1
+ import "core-js/modules/es.set.difference.v2.js";
2
+ import "core-js/modules/es.set.intersection.v2.js";
3
+ import "core-js/modules/es.set.is-disjoint-from.v2.js";
4
+ import "core-js/modules/es.set.is-subset-of.v2.js";
5
+ import "core-js/modules/es.set.is-superset-of.v2.js";
6
+ import "core-js/modules/es.set.symmetric-difference.v2.js";
7
+ import "core-js/modules/es.set.union.v2.js";
8
8
  /* eslint-disable jsdoc/require-description-complete-sentence */
9
9
  /**
10
10
  * Checks if the passed value is numeric one. For example these values (passed as string or number)
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "url": "https://github.com/handsontable/handsontable/issues"
11
11
  },
12
12
  "author": "Handsoncode <hello@handsontable.com>",
13
- "version": "14.5.0",
13
+ "version": "14.6.0-next-6fbf568-20240930",
14
14
  "main": "index",
15
15
  "module": "index.mjs",
16
16
  "jsnext:main": "index.mjs",
package/pluginHooks.d.ts CHANGED
@@ -180,7 +180,7 @@ export interface Events {
180
180
  beforeDrawBorders?: (corners: number[], borderClassName: 'current' | 'area' | 'highlight' | undefined) => void;
181
181
  beforeDropdownMenuSetItems?: (menuItems: ContextMenuMenuItemConfig[]) => void;
182
182
  beforeDropdownMenuShow?: (instance: DropdownMenu) => void;
183
- beforeFilter?: (conditionsStack: FiltersColumnConditions[]) => void | boolean;
183
+ beforeFilter?: (conditionsStack: FiltersColumnConditions[], previousConditionsStack: FiltersColumnConditions[]) => void | boolean;
184
184
  beforeGetCellMeta?: (row: number, column: number, cellProperties: CellProperties) => void;
185
185
  beforeHideColumns?: (currentHideConfig: number[], destinationHideConfig: number[], actionPossible: boolean) => void | boolean;
186
186
  beforeHideRows?: (currentHideConfig: number[], destinationHideConfig: number[], actionPossible: boolean) => void | boolean;
package/pluginHooks.js CHANGED
@@ -1953,7 +1953,9 @@ const REGISTERED_HOOKS = [/* eslint-disable jsdoc/require-description-complete-s
1953
1953
  * Fired by the [`Filters`](@/api/filters.md) plugin,
1954
1954
  * before a [column filter](@/guides/columns/column-filter/column-filter.md) gets applied.
1955
1955
  *
1956
- * [`beforeFilter`](#beforefilter) takes one argument (`conditionsStack`), which is an array of objects.
1956
+ * [`beforeFilter`](#beforefilter) takes two arguments: `conditionsStack` and `previousConditionsStack`, both are
1957
+ * arrays of objects.
1958
+ *
1957
1959
  * Each object represents one of your [column filters](@/api/filters.md#addcondition),
1958
1960
  * and consists of the following properties:
1959
1961
  *
@@ -2004,6 +2006,7 @@ const REGISTERED_HOOKS = [/* eslint-disable jsdoc/require-description-complete-s
2004
2006
  *
2005
2007
  * @event Hooks#beforeFilter
2006
2008
  * @param {object[]} conditionsStack An array of objects with your [column filters](@/api/filters.md#addcondition).
2009
+ * @param {object[]|null} previousConditionsStack An array of objects with your previous [column filters](@/api/filters.md#addcondition). It can also be `null` if there was no previous filters applied or the conditions did not change between performing the `filter` action.
2007
2010
  * @returns {boolean} To perform server-side filtering (i.e., to not apply filtering to Handsontable's UI), return `false`.
2008
2011
  */
2009
2012
  'beforeFilter',
package/pluginHooks.mjs CHANGED
@@ -1949,7 +1949,9 @@ const REGISTERED_HOOKS = [/* eslint-disable jsdoc/require-description-complete-s
1949
1949
  * Fired by the [`Filters`](@/api/filters.md) plugin,
1950
1950
  * before a [column filter](@/guides/columns/column-filter/column-filter.md) gets applied.
1951
1951
  *
1952
- * [`beforeFilter`](#beforefilter) takes one argument (`conditionsStack`), which is an array of objects.
1952
+ * [`beforeFilter`](#beforefilter) takes two arguments: `conditionsStack` and `previousConditionsStack`, both are
1953
+ * arrays of objects.
1954
+ *
1953
1955
  * Each object represents one of your [column filters](@/api/filters.md#addcondition),
1954
1956
  * and consists of the following properties:
1955
1957
  *
@@ -2000,6 +2002,7 @@ const REGISTERED_HOOKS = [/* eslint-disable jsdoc/require-description-complete-s
2000
2002
  *
2001
2003
  * @event Hooks#beforeFilter
2002
2004
  * @param {object[]} conditionsStack An array of objects with your [column filters](@/api/filters.md#addcondition).
2005
+ * @param {object[]|null} previousConditionsStack An array of objects with your previous [column filters](@/api/filters.md#addcondition). It can also be `null` if there was no previous filters applied or the conditions did not change between performing the `filter` action.
2003
2006
  * @returns {boolean} To perform server-side filtering (i.e., to not apply filtering to Handsontable's UI), return `false`.
2004
2007
  */
2005
2008
  'beforeFilter',
@@ -37,8 +37,7 @@ const ROW_WIDTHS_MAP_NAME = 'autoRowSize';
37
37
  * resize the rows accordingly.
38
38
  * If you experience problems with the performance, try turning this feature off and declaring the row heights manually.
39
39
  *
40
- * But, to display Handsontable's [scrollbar](https://handsontable.com/docs/8.0.0/demo-scrolling.html)
41
- * in a proper size, you need to enable the `AutoRowSize` plugin,
40
+ * But, to display Handsontable's scrollbar in a proper size, you need to enable the `AutoRowSize` plugin,
42
41
  * by setting the [`autoRowSize`](@/api/options.md#autoRowSize) option to `true`.
43
42
  *
44
43
  * Row height calculations are divided into sync and async part. Each of this parts has their own advantages and
@@ -33,8 +33,7 @@ const ROW_WIDTHS_MAP_NAME = 'autoRowSize';
33
33
  * resize the rows accordingly.
34
34
  * If you experience problems with the performance, try turning this feature off and declaring the row heights manually.
35
35
  *
36
- * But, to display Handsontable's [scrollbar](https://handsontable.com/docs/8.0.0/demo-scrolling.html)
37
- * in a proper size, you need to enable the `AutoRowSize` plugin,
36
+ * But, to display Handsontable's scrollbar in a proper size, you need to enable the `AutoRowSize` plugin,
38
37
  * by setting the [`autoRowSize`](@/api/options.md#autoRowSize) option to `true`.
39
38
  *
40
39
  * Row height calculations are divided into sync and async part. Each of this parts has their own advantages and
@@ -722,7 +722,16 @@ class ColumnSorting extends _base.BasePlugin {
722
722
  this.hot.deselectCell();
723
723
  this.hot.selectColumns(coords.col);
724
724
  }
725
- this.sort(this.getColumnNextConfig(coords.col));
725
+ const activeEditor = this.hot.getActiveEditor();
726
+ const nextConfig = this.getColumnNextConfig(coords.col);
727
+ if (activeEditor !== null && activeEditor !== void 0 && activeEditor.isOpened() && this.hot.getCellValidator(activeEditor.row, activeEditor.col)) {
728
+ // Postpone sorting until the cell's value is validated and saved.
729
+ this.hot.addHookOnce('postAfterValidate', () => {
730
+ this.sort(nextConfig);
731
+ });
732
+ } else {
733
+ this.sort(nextConfig);
734
+ }
726
735
  }
727
736
  }
728
737
 
@@ -718,7 +718,16 @@ export class ColumnSorting extends BasePlugin {
718
718
  this.hot.deselectCell();
719
719
  this.hot.selectColumns(coords.col);
720
720
  }
721
- this.sort(this.getColumnNextConfig(coords.col));
721
+ const activeEditor = this.hot.getActiveEditor();
722
+ const nextConfig = this.getColumnNextConfig(coords.col);
723
+ if (activeEditor !== null && activeEditor !== void 0 && activeEditor.isOpened() && this.hot.getCellValidator(activeEditor.row, activeEditor.col)) {
724
+ // Postpone sorting until the cell's value is validated and saved.
725
+ this.hot.addHookOnce('postAfterValidate', () => {
726
+ this.sort(nextConfig);
727
+ });
728
+ } else {
729
+ this.sort(nextConfig);
730
+ }
722
731
  }
723
732
  }
724
733
 
@@ -7,13 +7,13 @@ exports.getHeaderSpanElement = getHeaderSpanElement;
7
7
  exports.getNextSortOrder = getNextSortOrder;
8
8
  exports.isFirstLevelColumnHeader = isFirstLevelColumnHeader;
9
9
  exports.wasHeaderClickedProperly = wasHeaderClickedProperly;
10
- require("core-js/modules/esnext.set.difference.v2.js");
11
- require("core-js/modules/esnext.set.intersection.v2.js");
12
- require("core-js/modules/esnext.set.is-disjoint-from.v2.js");
13
- require("core-js/modules/esnext.set.is-subset-of.v2.js");
14
- require("core-js/modules/esnext.set.is-superset-of.v2.js");
15
- require("core-js/modules/esnext.set.symmetric-difference.v2.js");
16
- require("core-js/modules/esnext.set.union.v2.js");
10
+ require("core-js/modules/es.set.difference.v2.js");
11
+ require("core-js/modules/es.set.intersection.v2.js");
12
+ require("core-js/modules/es.set.is-disjoint-from.v2.js");
13
+ require("core-js/modules/es.set.is-subset-of.v2.js");
14
+ require("core-js/modules/es.set.is-superset-of.v2.js");
15
+ require("core-js/modules/es.set.symmetric-difference.v2.js");
16
+ require("core-js/modules/es.set.union.v2.js");
17
17
  var _moment = _interopRequireDefault(require("moment"));
18
18
  var _object = require("../../helpers/object");
19
19
  var _event = require("../../helpers/dom/event");
@@ -1,10 +1,10 @@
1
- import "core-js/modules/esnext.set.difference.v2.js";
2
- import "core-js/modules/esnext.set.intersection.v2.js";
3
- import "core-js/modules/esnext.set.is-disjoint-from.v2.js";
4
- import "core-js/modules/esnext.set.is-subset-of.v2.js";
5
- import "core-js/modules/esnext.set.is-superset-of.v2.js";
6
- import "core-js/modules/esnext.set.symmetric-difference.v2.js";
7
- import "core-js/modules/esnext.set.union.v2.js";
1
+ import "core-js/modules/es.set.difference.v2.js";
2
+ import "core-js/modules/es.set.intersection.v2.js";
3
+ import "core-js/modules/es.set.is-disjoint-from.v2.js";
4
+ import "core-js/modules/es.set.is-subset-of.v2.js";
5
+ import "core-js/modules/es.set.is-superset-of.v2.js";
6
+ import "core-js/modules/es.set.symmetric-difference.v2.js";
7
+ import "core-js/modules/es.set.union.v2.js";
8
8
  import moment from 'moment';
9
9
  import { isObject } from "../../helpers/object.mjs";
10
10
  import { isRightClick } from "../../helpers/dom/event.mjs";
@@ -237,6 +237,13 @@ class ContextMenu extends _base.BasePlugin {
237
237
  }
238
238
  this.prepareMenuItems();
239
239
  this.menu.open();
240
+ const themeHasTableBorder = this.menu.tableBorderWidth > 0;
241
+ if (!themeHasTableBorder) {
242
+ offset.below += 1;
243
+ offset.right += 1;
244
+ offset.above -= 1;
245
+ offset.left -= 1;
246
+ }
240
247
  (0, _object.objectEach)(offset, (value, key) => {
241
248
  this.menu.setOffset(key, value);
242
249
  });
@@ -233,6 +233,13 @@ export class ContextMenu extends BasePlugin {
233
233
  }
234
234
  this.prepareMenuItems();
235
235
  this.menu.open();
236
+ const themeHasTableBorder = this.menu.tableBorderWidth > 0;
237
+ if (!themeHasTableBorder) {
238
+ offset.below += 1;
239
+ offset.right += 1;
240
+ offset.above -= 1;
241
+ offset.left -= 1;
242
+ }
236
243
  objectEach(offset, (value, key) => {
237
244
  this.menu.setOffset(key, value);
238
245
  });
@@ -47,7 +47,21 @@ const MIN_WIDTH = 215;
47
47
  */
48
48
  var _navigator = /*#__PURE__*/new WeakMap();
49
49
  var _shortcutsCtrl = /*#__PURE__*/new WeakMap();
50
+ var _tableBorderWidth = /*#__PURE__*/new WeakMap();
50
51
  class Menu {
52
+ /**
53
+ * Getter for the table border width.
54
+ * This getter retrieves the border width of the table used in the menu.
55
+ *
56
+ * @returns {number} The border width of the table in pixels.
57
+ */
58
+ get tableBorderWidth() {
59
+ if (_classPrivateFieldGet(_tableBorderWidth, this) === undefined && this.hotMenu) {
60
+ _classPrivateFieldSet(_tableBorderWidth, this, parseInt((0, _element.getComputedStyle)(this.hotMenu.view._wt.wtTable.TABLE).borderWidth, 10));
61
+ }
62
+ return _classPrivateFieldGet(_tableBorderWidth, this);
63
+ }
64
+
51
65
  /**
52
66
  * @param {Core} hotInstance Handsontable instance.
53
67
  * @param {MenuOptions} [options] Menu options.
@@ -120,6 +134,12 @@ class Menu {
120
134
  * @type {KeyboardShortcutsMenuController}
121
135
  */
122
136
  _classPrivateFieldInitSpec(this, _shortcutsCtrl, void 0);
137
+ /**
138
+ * The border width of the table used in the menu.
139
+ *
140
+ * @type {number}
141
+ */
142
+ _classPrivateFieldInitSpec(this, _tableBorderWidth, void 0);
123
143
  this.hot = hotInstance;
124
144
  this.options = options || {
125
145
  parent: null,
@@ -276,7 +296,7 @@ class Menu {
276
296
  this.openSubMenu(coords.row);
277
297
  }
278
298
  },
279
- rowHeights: row => filteredItems[row].name === _predefinedItems.SEPARATOR ? 1 : 23,
299
+ rowHeights: row => filteredItems[row].name === _predefinedItems.SEPARATOR ? 1 : undefined,
280
300
  afterOnCellContextMenu: event => {
281
301
  event.preventDefault();
282
302
 
@@ -541,6 +561,31 @@ class Menu {
541
561
  this.positioner.setElement(this.container).updatePosition(coords);
542
562
  }
543
563
 
564
+ /**
565
+ * Updates the dimensions of the menu based on its content.
566
+ * This method calculates the real height of the menu by summing up the heights of its items,
567
+ * and adjusts the width and height of the menu's holder and hider elements accordingly.
568
+ */
569
+ updateMenuDimensions() {
570
+ const {
571
+ wtTable
572
+ } = this.hotMenu.view._wt;
573
+ const data = this.hotMenu.getSettings().data;
574
+ const hiderStyle = wtTable.hider.style;
575
+ const holderStyle = wtTable.holder.style;
576
+ const currentHiderWidth = parseInt(hiderStyle.width, 10);
577
+ const realHeight = (0, _array.arrayReduce)(data, (accumulator, value, index) => {
578
+ const itemCell = this.hotMenu.getCell(index, 0);
579
+ const currentRowHeight = itemCell ? (0, _element.outerHeight)(this.hotMenu.getCell(index, 0)) : 0;
580
+ return accumulator + (value.name === _predefinedItems.SEPARATOR ? 1 : currentRowHeight);
581
+ }, 0);
582
+
583
+ // Additional 3px to menu's size because of additional border around its `table.htCore`.
584
+ holderStyle.width = `${currentHiderWidth + 3}px`;
585
+ holderStyle.height = `${realHeight + 3}px`;
586
+ hiderStyle.height = holderStyle.height;
587
+ }
588
+
544
589
  /**
545
590
  * Create container/wrapper for handsontable.
546
591
  *
@@ -583,19 +628,7 @@ class Menu {
583
628
  * @private
584
629
  */
585
630
  onAfterInit() {
586
- const {
587
- wtTable
588
- } = this.hotMenu.view._wt;
589
- const data = this.hotMenu.getSettings().data;
590
- const hiderStyle = wtTable.hider.style;
591
- const holderStyle = wtTable.holder.style;
592
- const currentHiderWidth = parseInt(hiderStyle.width, 10);
593
- const realHeight = (0, _array.arrayReduce)(data, (accumulator, value) => accumulator + (value.name === _predefinedItems.SEPARATOR ? 1 : 26), 0);
594
-
595
- // Additional 3px to menu's size because of additional border around its `table.htCore`.
596
- holderStyle.width = `${currentHiderWidth + 3}px`;
597
- holderStyle.height = `${realHeight + 3}px`;
598
- hiderStyle.height = holderStyle.height;
631
+ this.updateMenuDimensions();
599
632
 
600
633
  // Replace the default accessibility tags with the context menu's
601
634
  if (this.hot.getSettings().ariaTags) {
@@ -16,7 +16,7 @@ import { filterSeparators, hasSubMenu, isItemHidden, normalizeSelection, isItemS
16
16
  import EventManager from "../../../eventManager.mjs";
17
17
  import { arrayEach, arrayFilter, arrayReduce } from "../../../helpers/array.mjs";
18
18
  import { isWindowsOS, isMobileBrowser, isIpadOS } from "../../../helpers/browser.mjs";
19
- import { addClass, isChildOf, getParentWindow, hasClass, setAttribute } from "../../../helpers/dom/element.mjs";
19
+ import { addClass, isChildOf, getComputedStyle, getParentWindow, hasClass, setAttribute, outerHeight } from "../../../helpers/dom/element.mjs";
20
20
  import { isRightClick } from "../../../helpers/dom/event.mjs";
21
21
  import { debounce, isFunction } from "../../../helpers/function.mjs";
22
22
  import { isUndefined, isDefined } from "../../../helpers/mixed.mjs";
@@ -43,7 +43,21 @@ const MIN_WIDTH = 215;
43
43
  */
44
44
  var _navigator = /*#__PURE__*/new WeakMap();
45
45
  var _shortcutsCtrl = /*#__PURE__*/new WeakMap();
46
+ var _tableBorderWidth = /*#__PURE__*/new WeakMap();
46
47
  export class Menu {
48
+ /**
49
+ * Getter for the table border width.
50
+ * This getter retrieves the border width of the table used in the menu.
51
+ *
52
+ * @returns {number} The border width of the table in pixels.
53
+ */
54
+ get tableBorderWidth() {
55
+ if (_classPrivateFieldGet(_tableBorderWidth, this) === undefined && this.hotMenu) {
56
+ _classPrivateFieldSet(_tableBorderWidth, this, parseInt(getComputedStyle(this.hotMenu.view._wt.wtTable.TABLE).borderWidth, 10));
57
+ }
58
+ return _classPrivateFieldGet(_tableBorderWidth, this);
59
+ }
60
+
47
61
  /**
48
62
  * @param {Core} hotInstance Handsontable instance.
49
63
  * @param {MenuOptions} [options] Menu options.
@@ -116,6 +130,12 @@ export class Menu {
116
130
  * @type {KeyboardShortcutsMenuController}
117
131
  */
118
132
  _classPrivateFieldInitSpec(this, _shortcutsCtrl, void 0);
133
+ /**
134
+ * The border width of the table used in the menu.
135
+ *
136
+ * @type {number}
137
+ */
138
+ _classPrivateFieldInitSpec(this, _tableBorderWidth, void 0);
119
139
  this.hot = hotInstance;
120
140
  this.options = options || {
121
141
  parent: null,
@@ -272,7 +292,7 @@ export class Menu {
272
292
  this.openSubMenu(coords.row);
273
293
  }
274
294
  },
275
- rowHeights: row => filteredItems[row].name === SEPARATOR ? 1 : 23,
295
+ rowHeights: row => filteredItems[row].name === SEPARATOR ? 1 : undefined,
276
296
  afterOnCellContextMenu: event => {
277
297
  event.preventDefault();
278
298
 
@@ -537,6 +557,31 @@ export class Menu {
537
557
  this.positioner.setElement(this.container).updatePosition(coords);
538
558
  }
539
559
 
560
+ /**
561
+ * Updates the dimensions of the menu based on its content.
562
+ * This method calculates the real height of the menu by summing up the heights of its items,
563
+ * and adjusts the width and height of the menu's holder and hider elements accordingly.
564
+ */
565
+ updateMenuDimensions() {
566
+ const {
567
+ wtTable
568
+ } = this.hotMenu.view._wt;
569
+ const data = this.hotMenu.getSettings().data;
570
+ const hiderStyle = wtTable.hider.style;
571
+ const holderStyle = wtTable.holder.style;
572
+ const currentHiderWidth = parseInt(hiderStyle.width, 10);
573
+ const realHeight = arrayReduce(data, (accumulator, value, index) => {
574
+ const itemCell = this.hotMenu.getCell(index, 0);
575
+ const currentRowHeight = itemCell ? outerHeight(this.hotMenu.getCell(index, 0)) : 0;
576
+ return accumulator + (value.name === SEPARATOR ? 1 : currentRowHeight);
577
+ }, 0);
578
+
579
+ // Additional 3px to menu's size because of additional border around its `table.htCore`.
580
+ holderStyle.width = `${currentHiderWidth + 3}px`;
581
+ holderStyle.height = `${realHeight + 3}px`;
582
+ hiderStyle.height = holderStyle.height;
583
+ }
584
+
540
585
  /**
541
586
  * Create container/wrapper for handsontable.
542
587
  *
@@ -579,19 +624,7 @@ export class Menu {
579
624
  * @private
580
625
  */
581
626
  onAfterInit() {
582
- const {
583
- wtTable
584
- } = this.hotMenu.view._wt;
585
- const data = this.hotMenu.getSettings().data;
586
- const hiderStyle = wtTable.hider.style;
587
- const holderStyle = wtTable.holder.style;
588
- const currentHiderWidth = parseInt(hiderStyle.width, 10);
589
- const realHeight = arrayReduce(data, (accumulator, value) => accumulator + (value.name === SEPARATOR ? 1 : 26), 0);
590
-
591
- // Additional 3px to menu's size because of additional border around its `table.htCore`.
592
- holderStyle.width = `${currentHiderWidth + 3}px`;
593
- holderStyle.height = `${realHeight + 3}px`;
594
- hiderStyle.height = holderStyle.height;
627
+ this.updateMenuDimensions();
595
628
 
596
629
  // Replace the default accessibility tags with the context menu's
597
630
  if (this.hot.getSettings().ariaTags) {
@@ -25,17 +25,16 @@ function createMenuItemRenderer(mainTableHot) {
25
25
  * @param {string} value The cell value.
26
26
  */
27
27
  return (menuHot, TD, row, col, prop, value) => {
28
- if (TD.hasAttribute('ghost-table')) {
29
- return;
30
- }
31
28
  const item = menuHot.getSourceDataAtRow(row);
32
29
  const wrapper = mainTableHot.rootDocument.createElement('div');
33
30
  const itemValue = typeof value === 'function' ? value.call(mainTableHot) : value;
31
+ const ariaLabel = typeof item.ariaLabel === 'function' ? item.ariaLabel.call(mainTableHot) : item.ariaLabel;
32
+ const ariaChecked = typeof item.ariaChecked === 'function' ? item.ariaChecked.call(mainTableHot) : item.ariaChecked;
34
33
  (0, _element.empty)(TD);
35
34
  (0, _element.addClass)(wrapper, 'htItemWrapper');
36
35
  if (mainTableHot.getSettings().ariaTags) {
37
36
  const isFocusable = !(0, _utils.isItemDisabled)(item, mainTableHot) && !(0, _utils.isItemSelectionDisabled)(item) && !(0, _utils.isItemSeparator)(item);
38
- (0, _element.setAttribute)(TD, [(0, _a11y.A11Y_MENU_ITEM)(), (0, _a11y.A11Y_LABEL)(itemValue), ...(isFocusable ? [(0, _a11y.A11Y_TABINDEX)(-1)] : []), ...((0, _utils.isItemDisabled)(item, mainTableHot) ? [(0, _a11y.A11Y_DISABLED)()] : []), ...((0, _utils.isItemSubMenu)(item) ? [(0, _a11y.A11Y_EXPANDED)(false)] : [])]);
37
+ (0, _element.setAttribute)(TD, [...((0, _utils.isItemCheckable)(item) ? [(0, _a11y.A11Y_MENU_ITEM_CHECKBOX)(), (0, _a11y.A11Y_LABEL)(ariaLabel), (0, _a11y.A11Y_CHECKED)(ariaChecked)] : [(0, _a11y.A11Y_MENU_ITEM)(), (0, _a11y.A11Y_LABEL)(itemValue)]), ...(isFocusable ? [(0, _a11y.A11Y_TABINDEX)(-1)] : []), ...((0, _utils.isItemDisabled)(item, mainTableHot) ? [(0, _a11y.A11Y_DISABLED)()] : []), ...((0, _utils.isItemSubMenu)(item) ? [(0, _a11y.A11Y_EXPANDED)(false)] : [])]);
39
38
  }
40
39
  TD.className = '';
41
40
  TD.appendChild(wrapper);
@@ -1,6 +1,6 @@
1
- import { isItemSubMenu, isItemDisabled, isItemSelectionDisabled, isItemSeparator } from "./utils.mjs";
1
+ import { isItemSubMenu, isItemDisabled, isItemSelectionDisabled, isItemSeparator, isItemCheckable } from "./utils.mjs";
2
2
  import { addClass, empty, fastInnerHTML, setAttribute } from "../../../helpers/dom/element.mjs";
3
- import { A11Y_DISABLED, A11Y_EXPANDED, A11Y_LABEL, A11Y_MENU_ITEM, A11Y_TABINDEX } from "../../../helpers/a11y.mjs";
3
+ import { A11Y_MENU_ITEM_CHECKBOX, A11Y_DISABLED, A11Y_EXPANDED, A11Y_LABEL, A11Y_MENU_ITEM, A11Y_TABINDEX, A11Y_CHECKED } from "../../../helpers/a11y.mjs";
4
4
  /**
5
5
  * Creates the menu renderer function.
6
6
  *
@@ -21,17 +21,16 @@ export function createMenuItemRenderer(mainTableHot) {
21
21
  * @param {string} value The cell value.
22
22
  */
23
23
  return (menuHot, TD, row, col, prop, value) => {
24
- if (TD.hasAttribute('ghost-table')) {
25
- return;
26
- }
27
24
  const item = menuHot.getSourceDataAtRow(row);
28
25
  const wrapper = mainTableHot.rootDocument.createElement('div');
29
26
  const itemValue = typeof value === 'function' ? value.call(mainTableHot) : value;
27
+ const ariaLabel = typeof item.ariaLabel === 'function' ? item.ariaLabel.call(mainTableHot) : item.ariaLabel;
28
+ const ariaChecked = typeof item.ariaChecked === 'function' ? item.ariaChecked.call(mainTableHot) : item.ariaChecked;
30
29
  empty(TD);
31
30
  addClass(wrapper, 'htItemWrapper');
32
31
  if (mainTableHot.getSettings().ariaTags) {
33
32
  const isFocusable = !isItemDisabled(item, mainTableHot) && !isItemSelectionDisabled(item) && !isItemSeparator(item);
34
- setAttribute(TD, [A11Y_MENU_ITEM(), A11Y_LABEL(itemValue), ...(isFocusable ? [A11Y_TABINDEX(-1)] : []), ...(isItemDisabled(item, mainTableHot) ? [A11Y_DISABLED()] : []), ...(isItemSubMenu(item) ? [A11Y_EXPANDED(false)] : [])]);
33
+ setAttribute(TD, [...(isItemCheckable(item) ? [A11Y_MENU_ITEM_CHECKBOX(), A11Y_LABEL(ariaLabel), A11Y_CHECKED(ariaChecked)] : [A11Y_MENU_ITEM(), A11Y_LABEL(itemValue)]), ...(isFocusable ? [A11Y_TABINDEX(-1)] : []), ...(isItemDisabled(item, mainTableHot) ? [A11Y_DISABLED()] : []), ...(isItemSubMenu(item) ? [A11Y_EXPANDED(false)] : [])]);
35
34
  }
36
35
  TD.className = '';
37
36
  TD.appendChild(wrapper);
@@ -165,12 +165,8 @@ class Positioner {
165
165
  setPositionOnRightOfCursor() {
166
166
  let left = _classPrivateFieldGet(_cursor, this).left;
167
167
  if (_classPrivateFieldGet(_parentContainer, this)) {
168
- const {
169
- right: parentMenuRight
170
- } = _classPrivateFieldGet(_parentContainer, this).getBoundingClientRect();
171
-
172
- // move the sub menu by the width of the parent's border (usually by 1-2 pixels)
173
- left += _classPrivateFieldGet(_cursor, this).cellWidth + parentMenuRight - (_classPrivateFieldGet(_cursor, this).left + _classPrivateFieldGet(_cursor, this).cellWidth);
168
+ const borderRightWidth = Number.parseInt(getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.htCore')).borderRightWidth, 10);
169
+ left += _classPrivateFieldGet(_cursor, this).cellWidth + borderRightWidth;
174
170
  } else {
175
171
  left += _classPrivateFieldGet(_offset, this).right;
176
172
  }
@@ -183,12 +179,8 @@ class Positioner {
183
179
  setPositionOnLeftOfCursor() {
184
180
  let left = _classPrivateFieldGet(_offset, this).left + _classPrivateFieldGet(_cursor, this).left - _classPrivateFieldGet(_container, this).offsetWidth;
185
181
  if (_classPrivateFieldGet(_parentContainer, this)) {
186
- const {
187
- left: parentMenuLeft
188
- } = _classPrivateFieldGet(_parentContainer, this).getBoundingClientRect();
189
-
190
- // move the sub menu by the width of the parent's border (usually by 1-2 pixels)
191
- left -= _classPrivateFieldGet(_cursor, this).left - parentMenuLeft;
182
+ const borderLeftWidth = Number.parseInt(getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.htCore')).borderLeftWidth, 10);
183
+ left -= borderLeftWidth;
192
184
  }
193
185
  _classPrivateFieldGet(_container, this).style.left = `${left}px`;
194
186
  }