handsontable 14.5.0 → 14.6.0-next-4d69faf-20240924

Sign up to get free protection for your applications and to get access to all the features.
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 +3498 -3219
  26. package/dist/handsontable.full.min.css +3 -3
  27. package/dist/handsontable.full.min.js +109 -119
  28. package/dist/handsontable.js +3172 -2897
  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 +1 -0
  43. package/pluginHooks.mjs +1 -0
  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-4d69faf-20240924";
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-4d69faf-20240924";
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-4d69faf-20240924",
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
@@ -2004,6 +2004,7 @@ const REGISTERED_HOOKS = [/* eslint-disable jsdoc/require-description-complete-s
2004
2004
  *
2005
2005
  * @event Hooks#beforeFilter
2006
2006
  * @param {object[]} conditionsStack An array of objects with your [column filters](@/api/filters.md#addcondition).
2007
+ * @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
2008
  * @returns {boolean} To perform server-side filtering (i.e., to not apply filtering to Handsontable's UI), return `false`.
2008
2009
  */
2009
2010
  'beforeFilter',
package/pluginHooks.mjs CHANGED
@@ -2000,6 +2000,7 @@ const REGISTERED_HOOKS = [/* eslint-disable jsdoc/require-description-complete-s
2000
2000
  *
2001
2001
  * @event Hooks#beforeFilter
2002
2002
  * @param {object[]} conditionsStack An array of objects with your [column filters](@/api/filters.md#addcondition).
2003
+ * @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
2004
  * @returns {boolean} To perform server-side filtering (i.e., to not apply filtering to Handsontable's UI), return `false`.
2004
2005
  */
2005
2006
  '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
  }
@@ -162,12 +162,8 @@ export class Positioner {
162
162
  setPositionOnRightOfCursor() {
163
163
  let left = _classPrivateFieldGet(_cursor, this).left;
164
164
  if (_classPrivateFieldGet(_parentContainer, this)) {
165
- const {
166
- right: parentMenuRight
167
- } = _classPrivateFieldGet(_parentContainer, this).getBoundingClientRect();
168
-
169
- // move the sub menu by the width of the parent's border (usually by 1-2 pixels)
170
- left += _classPrivateFieldGet(_cursor, this).cellWidth + parentMenuRight - (_classPrivateFieldGet(_cursor, this).left + _classPrivateFieldGet(_cursor, this).cellWidth);
165
+ const borderRightWidth = Number.parseInt(getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.htCore')).borderRightWidth, 10);
166
+ left += _classPrivateFieldGet(_cursor, this).cellWidth + borderRightWidth;
171
167
  } else {
172
168
  left += _classPrivateFieldGet(_offset, this).right;
173
169
  }
@@ -180,12 +176,8 @@ export class Positioner {
180
176
  setPositionOnLeftOfCursor() {
181
177
  let left = _classPrivateFieldGet(_offset, this).left + _classPrivateFieldGet(_cursor, this).left - _classPrivateFieldGet(_container, this).offsetWidth;
182
178
  if (_classPrivateFieldGet(_parentContainer, this)) {
183
- const {
184
- left: parentMenuLeft
185
- } = _classPrivateFieldGet(_parentContainer, this).getBoundingClientRect();
186
-
187
- // move the sub menu by the width of the parent's border (usually by 1-2 pixels)
188
- left -= _classPrivateFieldGet(_cursor, this).left - parentMenuLeft;
179
+ const borderLeftWidth = Number.parseInt(getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.htCore')).borderLeftWidth, 10);
180
+ left -= borderLeftWidth;
189
181
  }
190
182
  _classPrivateFieldGet(_container, this).style.left = `${left}px`;
191
183
  }