handsontable 0.0.0-next-0306a1a-20240826 → 0.0.0-next-1dfe61f-20240910

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of handsontable might be problematic. Click here for more details.

Files changed (106) hide show
  1. package/3rdparty/walkontable/src/calculator/calculationType/fullyVisibleColumns.js +126 -0
  2. package/3rdparty/walkontable/src/calculator/calculationType/fullyVisibleColumns.mjs +122 -0
  3. package/3rdparty/walkontable/src/calculator/calculationType/fullyVisibleRows.js +119 -0
  4. package/3rdparty/walkontable/src/calculator/calculationType/fullyVisibleRows.mjs +115 -0
  5. package/3rdparty/walkontable/src/calculator/calculationType/partiallyVisibleColumns.js +125 -0
  6. package/3rdparty/walkontable/src/calculator/calculationType/partiallyVisibleColumns.mjs +121 -0
  7. package/3rdparty/walkontable/src/calculator/calculationType/partiallyVisibleRows.js +118 -0
  8. package/3rdparty/walkontable/src/calculator/calculationType/partiallyVisibleRows.mjs +114 -0
  9. package/3rdparty/walkontable/src/calculator/{renderAllColumns.js → calculationType/renderedAllColumns.js} +32 -9
  10. package/3rdparty/walkontable/src/calculator/{renderAllColumns.mjs → calculationType/renderedAllColumns.mjs} +31 -8
  11. package/3rdparty/walkontable/src/calculator/{renderAllRows.js → calculationType/renderedAllRows.js} +32 -9
  12. package/3rdparty/walkontable/src/calculator/{renderAllRows.mjs → calculationType/renderedAllRows.mjs} +31 -8
  13. package/3rdparty/walkontable/src/calculator/calculationType/renderedColumns.js +37 -0
  14. package/3rdparty/walkontable/src/calculator/calculationType/renderedColumns.mjs +33 -0
  15. package/3rdparty/walkontable/src/calculator/calculationType/renderedRows.js +37 -0
  16. package/3rdparty/walkontable/src/calculator/calculationType/renderedRows.mjs +33 -0
  17. package/3rdparty/walkontable/src/calculator/index.js +18 -17
  18. package/3rdparty/walkontable/src/calculator/index.mjs +11 -6
  19. package/3rdparty/walkontable/src/calculator/viewportBase.js +92 -0
  20. package/3rdparty/walkontable/src/calculator/viewportBase.mjs +88 -0
  21. package/3rdparty/walkontable/src/calculator/viewportColumns.js +51 -145
  22. package/3rdparty/walkontable/src/calculator/viewportColumns.mjs +51 -145
  23. package/3rdparty/walkontable/src/calculator/viewportRows.js +59 -141
  24. package/3rdparty/walkontable/src/calculator/viewportRows.mjs +59 -141
  25. package/3rdparty/walkontable/src/index.js +2 -0
  26. package/3rdparty/walkontable/src/index.mjs +2 -2
  27. package/3rdparty/walkontable/src/renderer/rows.js +10 -0
  28. package/3rdparty/walkontable/src/renderer/rows.mjs +11 -1
  29. package/3rdparty/walkontable/src/table.js +5 -11
  30. package/3rdparty/walkontable/src/table.mjs +5 -11
  31. package/3rdparty/walkontable/src/utils/column.js +2 -1
  32. package/3rdparty/walkontable/src/utils/column.mjs +2 -1
  33. package/3rdparty/walkontable/src/utils/columnStretching.js +10 -19
  34. package/3rdparty/walkontable/src/utils/columnStretching.mjs +10 -19
  35. package/3rdparty/walkontable/src/viewport.js +35 -46
  36. package/3rdparty/walkontable/src/viewport.mjs +36 -47
  37. package/CHANGELOG.md +27 -0
  38. package/base.js +2 -2
  39. package/base.mjs +2 -2
  40. package/core.d.ts +1 -2
  41. package/core.js +1 -1
  42. package/core.mjs +2 -2
  43. package/dataMap/metaManager/metaSchema.js +5 -6
  44. package/dataMap/metaManager/metaSchema.mjs +5 -6
  45. package/dist/handsontable.css +32 -20
  46. package/dist/handsontable.full.css +32 -20
  47. package/dist/handsontable.full.js +2751 -2091
  48. package/dist/handsontable.full.min.css +5 -5
  49. package/dist/handsontable.full.min.js +148 -148
  50. package/dist/handsontable.js +2752 -2092
  51. package/dist/handsontable.min.css +4 -4
  52. package/dist/handsontable.min.js +32 -32
  53. package/editors/autocompleteEditor/autocompleteEditor.d.ts +1 -1
  54. package/helpers/a11y.js +2 -0
  55. package/helpers/a11y.mjs +1 -0
  56. package/helpers/mixed.js +2 -2
  57. package/helpers/mixed.mjs +2 -2
  58. package/package.json +1 -1
  59. package/pluginHooks.d.ts +1 -1
  60. package/pluginHooks.js +1 -1
  61. package/pluginHooks.mjs +1 -1
  62. package/plugins/autoColumnSize/autoColumnSize.js +1 -1
  63. package/plugins/autoColumnSize/autoColumnSize.mjs +2 -2
  64. package/plugins/autoRowSize/autoRowSize.js +1 -2
  65. package/plugins/autoRowSize/autoRowSize.mjs +1 -2
  66. package/plugins/columnSorting/columnSorting.js +10 -1
  67. package/plugins/columnSorting/columnSorting.mjs +10 -1
  68. package/plugins/contextMenu/menu/menuItemRenderer.js +3 -4
  69. package/plugins/contextMenu/menu/menuItemRenderer.mjs +5 -6
  70. package/plugins/contextMenu/menu/positioner.js +4 -12
  71. package/plugins/contextMenu/menu/positioner.mjs +4 -12
  72. package/plugins/contextMenu/menu/utils.js +11 -0
  73. package/plugins/contextMenu/menu/utils.mjs +10 -0
  74. package/plugins/contextMenu/predefinedItems/alignment.js +67 -49
  75. package/plugins/contextMenu/predefinedItems/alignment.mjs +68 -50
  76. package/plugins/contextMenu/predefinedItems/readOnly.js +11 -0
  77. package/plugins/contextMenu/predefinedItems/readOnly.mjs +11 -0
  78. package/plugins/contextMenu/utils.js +26 -0
  79. package/plugins/contextMenu/utils.mjs +24 -0
  80. package/plugins/copyPaste/copyPaste.js +14 -14
  81. package/plugins/copyPaste/copyPaste.mjs +14 -14
  82. package/plugins/dropdownMenu/dropdownMenu.js +10 -4
  83. package/plugins/dropdownMenu/dropdownMenu.mjs +10 -4
  84. package/plugins/filters/component/condition.js +6 -1
  85. package/plugins/filters/component/condition.mjs +6 -1
  86. package/plugins/filters/component/value.js +6 -1
  87. package/plugins/filters/component/value.mjs +6 -1
  88. package/plugins/filters/conditionCollection.d.ts +4 -3
  89. package/plugins/filters/conditionCollection.js +26 -0
  90. package/plugins/filters/conditionCollection.mjs +26 -0
  91. package/plugins/filters/filters.js +2 -1
  92. package/plugins/filters/filters.mjs +2 -1
  93. package/plugins/filters/ui/multipleSelect.js +7 -9
  94. package/plugins/filters/ui/multipleSelect.mjs +7 -9
  95. package/plugins/manualRowResize/manualRowResize.js +1 -1
  96. package/plugins/manualRowResize/manualRowResize.mjs +2 -2
  97. package/plugins/mergeCells/cellsCollection.js +11 -9
  98. package/plugins/mergeCells/cellsCollection.mjs +12 -10
  99. package/plugins/undoRedo/undoRedo.js +9 -5
  100. package/plugins/undoRedo/undoRedo.mjs +9 -5
  101. package/shortcuts/utils.js +3 -1
  102. package/shortcuts/utils.mjs +3 -1
  103. package/utils/ghostTable.js +11 -9
  104. package/utils/ghostTable.mjs +12 -10
  105. package/3rdparty/walkontable/src/calculator/constants.js +0 -26
  106. package/3rdparty/walkontable/src/calculator/constants.mjs +0 -23
@@ -1,8 +1,19 @@
1
- import { align, getAlignmentClasses, checkSelectionConsistency, markLabelAsSelected } from "../utils.mjs";
1
+ import { align, getAlignmentClasses, markLabelAsSelected, hasSelectionAClass } from "../utils.mjs";
2
2
  import { KEY as SEPARATOR } from "./separator.mjs";
3
3
  import * as C from "../../../i18n/constants.mjs";
4
4
  export const KEY = 'alignment';
5
5
 
6
+ /**
7
+ * @param {object} hot The current Handsontable instance.
8
+ * @param {string} rawName The raw name of the menu item.
9
+ * @param {string} htClassName The class name to check.
10
+ * @returns {string} The value of aria-label parameter.
11
+ */
12
+ function ariaLabel(hot, rawName, htClassName) {
13
+ const checkboxState = hasSelectionAClass(hot, htClassName) ? hot.getTranslatedPhrase(C.CHECKBOX_CHECKED) : hot.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
14
+ return `${rawName} ${checkboxState.toLowerCase()}`;
15
+ }
16
+
6
17
  /**
7
18
  * @returns {object}
8
19
  */
@@ -28,15 +39,16 @@ export default function alignmentItem() {
28
39
  submenu: {
29
40
  items: [{
30
41
  key: `${KEY}:left`,
42
+ checkable: true,
43
+ ariaLabel() {
44
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT), 'htLeft');
45
+ },
46
+ ariaChecked() {
47
+ return hasSelectionAClass(this, 'htLeft');
48
+ },
31
49
  name() {
32
50
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT);
33
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
34
- const className = this.getCellMeta(row, col).className;
35
- if (className && className.indexOf('htLeft') !== -1) {
36
- return true;
37
- }
38
- });
39
- if (hasClass) {
51
+ if (hasSelectionAClass(this, 'htLeft')) {
40
52
  label = markLabelAsSelected(label);
41
53
  }
42
54
  return label;
@@ -53,15 +65,16 @@ export default function alignmentItem() {
53
65
  disabled: false
54
66
  }, {
55
67
  key: `${KEY}:center`,
68
+ checkable: true,
69
+ ariaLabel() {
70
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER), 'htCenter');
71
+ },
72
+ ariaChecked() {
73
+ return hasSelectionAClass(this, 'htCenter');
74
+ },
56
75
  name() {
57
76
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER);
58
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
59
- const className = this.getCellMeta(row, col).className;
60
- if (className && className.indexOf('htCenter') !== -1) {
61
- return true;
62
- }
63
- });
64
- if (hasClass) {
77
+ if (hasSelectionAClass(this, 'htCenter')) {
65
78
  label = markLabelAsSelected(label);
66
79
  }
67
80
  return label;
@@ -78,15 +91,16 @@ export default function alignmentItem() {
78
91
  disabled: false
79
92
  }, {
80
93
  key: `${KEY}:right`,
94
+ checkable: true,
95
+ ariaLabel() {
96
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT), 'htRight');
97
+ },
98
+ ariaChecked() {
99
+ return hasSelectionAClass(this, 'htRight');
100
+ },
81
101
  name() {
82
102
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT);
83
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
84
- const className = this.getCellMeta(row, col).className;
85
- if (className && className.indexOf('htRight') !== -1) {
86
- return true;
87
- }
88
- });
89
- if (hasClass) {
103
+ if (hasSelectionAClass(this, 'htRight')) {
90
104
  label = markLabelAsSelected(label);
91
105
  }
92
106
  return label;
@@ -103,15 +117,16 @@ export default function alignmentItem() {
103
117
  disabled: false
104
118
  }, {
105
119
  key: `${KEY}:justify`,
120
+ checkable: true,
121
+ ariaLabel() {
122
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY), 'htJustify');
123
+ },
124
+ ariaChecked() {
125
+ return hasSelectionAClass(this, 'htJustify');
126
+ },
106
127
  name() {
107
128
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY);
108
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
109
- const className = this.getCellMeta(row, col).className;
110
- if (className && className.indexOf('htJustify') !== -1) {
111
- return true;
112
- }
113
- });
114
- if (hasClass) {
129
+ if (hasSelectionAClass(this, 'htJustify')) {
115
130
  label = markLabelAsSelected(label);
116
131
  }
117
132
  return label;
@@ -130,15 +145,16 @@ export default function alignmentItem() {
130
145
  name: SEPARATOR
131
146
  }, {
132
147
  key: `${KEY}:top`,
148
+ checkable: true,
149
+ ariaLabel() {
150
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP), 'htTop');
151
+ },
152
+ ariaChecked() {
153
+ return hasSelectionAClass(this, 'htTop');
154
+ },
133
155
  name() {
134
156
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP);
135
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
136
- const className = this.getCellMeta(row, col).className;
137
- if (className && className.indexOf('htTop') !== -1) {
138
- return true;
139
- }
140
- });
141
- if (hasClass) {
157
+ if (hasSelectionAClass(this, 'htTop')) {
142
158
  label = markLabelAsSelected(label);
143
159
  }
144
160
  return label;
@@ -155,15 +171,16 @@ export default function alignmentItem() {
155
171
  disabled: false
156
172
  }, {
157
173
  key: `${KEY}:middle`,
174
+ checkable: true,
175
+ ariaLabel() {
176
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE), 'htMiddle');
177
+ },
178
+ ariaChecked() {
179
+ return hasSelectionAClass(this, 'htMiddle');
180
+ },
158
181
  name() {
159
182
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE);
160
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
161
- const className = this.getCellMeta(row, col).className;
162
- if (className && className.indexOf('htMiddle') !== -1) {
163
- return true;
164
- }
165
- });
166
- if (hasClass) {
183
+ if (hasSelectionAClass(this, 'htMiddle')) {
167
184
  label = markLabelAsSelected(label);
168
185
  }
169
186
  return label;
@@ -180,15 +197,16 @@ export default function alignmentItem() {
180
197
  disabled: false
181
198
  }, {
182
199
  key: `${KEY}:bottom`,
200
+ checkable: true,
201
+ ariaLabel() {
202
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM), 'htBottom');
203
+ },
204
+ ariaChecked() {
205
+ return hasSelectionAClass(this, 'htBottom');
206
+ },
183
207
  name() {
184
208
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM);
185
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
186
- const className = this.getCellMeta(row, col).className;
187
- if (className && className.indexOf('htBottom') !== -1) {
188
- return true;
189
- }
190
- });
191
- if (hasClass) {
209
+ if (hasSelectionAClass(this, 'htBottom')) {
192
210
  label = markLabelAsSelected(label);
193
211
  }
194
212
  return label;
@@ -15,6 +15,17 @@ const KEY = exports.KEY = 'make_read_only';
15
15
  function readOnlyItem() {
16
16
  return {
17
17
  key: KEY,
18
+ checkable: true,
19
+ ariaChecked() {
20
+ const atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
21
+ return atLeastOneReadOnly;
22
+ },
23
+ ariaLabel() {
24
+ const rawName = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
25
+ const atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
26
+ const checkboxState = atLeastOneReadOnly ? this.getTranslatedPhrase(C.CHECKBOX_CHECKED) : this.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
27
+ return `${rawName} ${checkboxState.toLowerCase()}`;
28
+ },
18
29
  name() {
19
30
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
20
31
  const atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
@@ -9,6 +9,17 @@ export const KEY = 'make_read_only';
9
9
  export default function readOnlyItem() {
10
10
  return {
11
11
  key: KEY,
12
+ checkable: true,
13
+ ariaChecked() {
14
+ const atLeastOneReadOnly = checkSelectionConsistency(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
15
+ return atLeastOneReadOnly;
16
+ },
17
+ ariaLabel() {
18
+ const rawName = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
19
+ const atLeastOneReadOnly = checkSelectionConsistency(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
20
+ const checkboxState = atLeastOneReadOnly ? this.getTranslatedPhrase(C.CHECKBOX_CHECKED) : this.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
21
+ return `${rawName} ${checkboxState.toLowerCase()}`;
22
+ },
12
23
  name() {
13
24
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
14
25
  const atLeastOneReadOnly = checkSelectionConsistency(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
@@ -4,7 +4,9 @@ exports.__esModule = true;
4
4
  exports.align = align;
5
5
  exports.checkSelectionConsistency = checkSelectionConsistency;
6
6
  exports.getAlignmentClasses = getAlignmentClasses;
7
+ exports.getAlignmentComparatorByClass = getAlignmentComparatorByClass;
7
8
  exports.getDocumentOffsetByElement = getDocumentOffsetByElement;
9
+ exports.hasSelectionAClass = hasSelectionAClass;
8
10
  exports.markLabelAsSelected = markLabelAsSelected;
9
11
  exports.prepareHorizontalAlignClass = prepareHorizontalAlignClass;
10
12
  exports.prepareVerticalAlignClass = prepareVerticalAlignClass;
@@ -151,4 +153,28 @@ function getDocumentOffsetByElement(elementToCheck, baseDocument) {
151
153
  offset.left = left;
152
154
  }
153
155
  return offset;
156
+ }
157
+
158
+ /**
159
+ * Prepares comparator function consumable by checkSelectionConsistency
160
+ * Comparator function checks if the cell has the provided class name.
161
+ *
162
+ * @param {string} htClassName The class name to check.
163
+ * @returns {Function} Returns the comparator function.
164
+ * Use with .bind, .call or .apply to pass the Handsontable instance.
165
+ */
166
+ function getAlignmentComparatorByClass(htClassName) {
167
+ return function (row, col) {
168
+ const className = this.getCellMeta(row, col).className;
169
+ return className && className.indexOf(htClassName) !== -1;
170
+ };
171
+ }
172
+
173
+ /**
174
+ * @param {object} hot Handsontable instance.
175
+ * @param {string} htClassName The class name to check.
176
+ * @returns {boolean} Returns true if at least one cell has the provided class name.
177
+ */
178
+ function hasSelectionAClass(hot, htClassName) {
179
+ return checkSelectionConsistency(hot.getSelectedRange(), getAlignmentComparatorByClass(htClassName).bind(hot));
154
180
  }
@@ -141,4 +141,28 @@ export function getDocumentOffsetByElement(elementToCheck, baseDocument) {
141
141
  offset.left = left;
142
142
  }
143
143
  return offset;
144
+ }
145
+
146
+ /**
147
+ * Prepares comparator function consumable by checkSelectionConsistency
148
+ * Comparator function checks if the cell has the provided class name.
149
+ *
150
+ * @param {string} htClassName The class name to check.
151
+ * @returns {Function} Returns the comparator function.
152
+ * Use with .bind, .call or .apply to pass the Handsontable instance.
153
+ */
154
+ export function getAlignmentComparatorByClass(htClassName) {
155
+ return function (row, col) {
156
+ const className = this.getCellMeta(row, col).className;
157
+ return className && className.indexOf(htClassName) !== -1;
158
+ };
159
+ }
160
+
161
+ /**
162
+ * @param {object} hot Handsontable instance.
163
+ * @param {string} htClassName The class name to check.
164
+ * @returns {boolean} Returns true if at least one cell has the provided class name.
165
+ */
166
+ export function hasSelectionAClass(hot, htClassName) {
167
+ return checkSelectionConsistency(hot.getSelectedRange(), getAlignmentComparatorByClass(htClassName).bind(hot));
144
168
  }
@@ -553,12 +553,13 @@ class CopyPaste extends _base.BasePlugin {
553
553
  * @private
554
554
  */
555
555
  onCopy(event) {
556
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened()) {
557
- return;
558
- }
559
- if (!this.hot.getSettings().outsideClickDeselects && event.target !== this.hot.rootDocument.body) {
556
+ var _event$target;
557
+ const focusedElement = this.hot.getFocusManager().getRefocusElement();
558
+ const isHotInput = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.hasAttribute('data-hot-input');
559
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body)) {
560
560
  return;
561
561
  }
562
+ event.preventDefault();
562
563
  this.setCopyableText();
563
564
  _classPrivateFieldSet(_isTriggeredByCopy, this, false);
564
565
  const data = this.getRangedData(this.copyableRanges);
@@ -576,7 +577,6 @@ class CopyPaste extends _base.BasePlugin {
576
577
  this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
577
578
  }
578
579
  _classPrivateFieldSet(_copyMode, this, 'cells-only');
579
- event.preventDefault();
580
580
  }
581
581
 
582
582
  /**
@@ -586,12 +586,13 @@ class CopyPaste extends _base.BasePlugin {
586
586
  * @private
587
587
  */
588
588
  onCut(event) {
589
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened()) {
590
- return;
591
- }
592
- if (!this.hot.getSettings().outsideClickDeselects && event.target !== this.hot.rootDocument.body) {
589
+ var _event$target2;
590
+ const focusedElement = this.hot.getFocusManager().getRefocusElement();
591
+ const isHotInput = (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.hasAttribute('data-hot-input');
592
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body)) {
593
593
  return;
594
594
  }
595
+ event.preventDefault();
595
596
  this.setCopyableText();
596
597
  _classPrivateFieldSet(_isTriggeredByCut, this, false);
597
598
  const rangedData = this.getRangedData(this.copyableRanges);
@@ -608,7 +609,6 @@ class CopyPaste extends _base.BasePlugin {
608
609
  this.hot.emptySelectedCells('CopyPaste.cut');
609
610
  this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
610
611
  }
611
- event.preventDefault();
612
612
  }
613
613
 
614
614
  /**
@@ -618,10 +618,10 @@ class CopyPaste extends _base.BasePlugin {
618
618
  * @private
619
619
  */
620
620
  onPaste(event) {
621
- if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected()) {
622
- return;
623
- }
624
- if (!this.hot.getSettings().outsideClickDeselects && event.target !== this.hot.rootDocument.body) {
621
+ var _event$target3;
622
+ const focusedElement = this.hot.getFocusManager().getRefocusElement();
623
+ const isHotInput = (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.hasAttribute('data-hot-input');
624
+ if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body)) {
625
625
  return;
626
626
  }
627
627
  event.preventDefault();
@@ -549,12 +549,13 @@ export class CopyPaste extends BasePlugin {
549
549
  * @private
550
550
  */
551
551
  onCopy(event) {
552
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened()) {
553
- return;
554
- }
555
- if (!this.hot.getSettings().outsideClickDeselects && event.target !== this.hot.rootDocument.body) {
552
+ var _event$target;
553
+ const focusedElement = this.hot.getFocusManager().getRefocusElement();
554
+ const isHotInput = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.hasAttribute('data-hot-input');
555
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body)) {
556
556
  return;
557
557
  }
558
+ event.preventDefault();
558
559
  this.setCopyableText();
559
560
  _classPrivateFieldSet(_isTriggeredByCopy, this, false);
560
561
  const data = this.getRangedData(this.copyableRanges);
@@ -572,7 +573,6 @@ export class CopyPaste extends BasePlugin {
572
573
  this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
573
574
  }
574
575
  _classPrivateFieldSet(_copyMode, this, 'cells-only');
575
- event.preventDefault();
576
576
  }
577
577
 
578
578
  /**
@@ -582,12 +582,13 @@ export class CopyPaste extends BasePlugin {
582
582
  * @private
583
583
  */
584
584
  onCut(event) {
585
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened()) {
586
- return;
587
- }
588
- if (!this.hot.getSettings().outsideClickDeselects && event.target !== this.hot.rootDocument.body) {
585
+ var _event$target2;
586
+ const focusedElement = this.hot.getFocusManager().getRefocusElement();
587
+ const isHotInput = (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.hasAttribute('data-hot-input');
588
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body)) {
589
589
  return;
590
590
  }
591
+ event.preventDefault();
591
592
  this.setCopyableText();
592
593
  _classPrivateFieldSet(_isTriggeredByCut, this, false);
593
594
  const rangedData = this.getRangedData(this.copyableRanges);
@@ -604,7 +605,6 @@ export class CopyPaste extends BasePlugin {
604
605
  this.hot.emptySelectedCells('CopyPaste.cut');
605
606
  this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
606
607
  }
607
- event.preventDefault();
608
608
  }
609
609
 
610
610
  /**
@@ -614,10 +614,10 @@ export class CopyPaste extends BasePlugin {
614
614
  * @private
615
615
  */
616
616
  onPaste(event) {
617
- if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected()) {
618
- return;
619
- }
620
- if (!this.hot.getSettings().outsideClickDeselects && event.target !== this.hot.rootDocument.body) {
617
+ var _event$target3;
618
+ const focusedElement = this.hot.getFocusManager().getRefocusElement();
619
+ const isHotInput = (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.hasAttribute('data-hot-input');
620
+ if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body)) {
621
621
  return;
622
622
  }
623
623
  event.preventDefault();
@@ -260,13 +260,16 @@ class DropdownMenu extends _base.BasePlugin {
260
260
  from
261
261
  } = this.hot.getSelectedRangeLast();
262
262
  const offset = (0, _utils.getDocumentOffsetByElement)(this.menu.container, this.hot.rootDocument);
263
- const target = this.hot.getCell(-1, from.col, true);
263
+ const target = this.hot.getCell(-1, from.col, true).querySelector(`.${BUTTON_CLASS_NAME}`);
264
264
  const rect = target.getBoundingClientRect();
265
265
  this.open({
266
266
  left: rect.left + offset.left,
267
267
  top: rect.top + target.offsetHeight + offset.top
268
268
  }, {
269
- left: rect.width
269
+ left: rect.width,
270
+ right: 0,
271
+ above: 0,
272
+ below: 3
270
273
  });
271
274
  // Make sure the first item is selected (role=menuitem). Otherwise, screen readers
272
275
  // will block the Esc key for the whole menu.
@@ -433,9 +436,12 @@ function _onTableClick(event) {
433
436
  _classPrivateFieldSet(_isButtonClicked, this, false);
434
437
  this.open({
435
438
  left: rect.left + offset.left,
436
- top: rect.top + event.target.offsetHeight + 3 + offset.top
439
+ top: rect.top + event.target.offsetHeight + offset.top
437
440
  }, {
438
- left: rect.width
441
+ left: rect.width,
442
+ right: 0,
443
+ above: 0,
444
+ below: 3
439
445
  });
440
446
  }
441
447
  }
@@ -256,13 +256,16 @@ export class DropdownMenu extends BasePlugin {
256
256
  from
257
257
  } = this.hot.getSelectedRangeLast();
258
258
  const offset = getDocumentOffsetByElement(this.menu.container, this.hot.rootDocument);
259
- const target = this.hot.getCell(-1, from.col, true);
259
+ const target = this.hot.getCell(-1, from.col, true).querySelector(`.${BUTTON_CLASS_NAME}`);
260
260
  const rect = target.getBoundingClientRect();
261
261
  this.open({
262
262
  left: rect.left + offset.left,
263
263
  top: rect.top + target.offsetHeight + offset.top
264
264
  }, {
265
- left: rect.width
265
+ left: rect.width,
266
+ right: 0,
267
+ above: 0,
268
+ below: 3
266
269
  });
267
270
  // Make sure the first item is selected (role=menuitem). Otherwise, screen readers
268
271
  // will block the Esc key for the whole menu.
@@ -428,9 +431,12 @@ function _onTableClick(event) {
428
431
  _classPrivateFieldSet(_isButtonClicked, this, false);
429
432
  this.open({
430
433
  left: rect.left + offset.left,
431
- top: rect.top + event.target.offsetHeight + 3 + offset.top
434
+ top: rect.top + event.target.offsetHeight + offset.top
432
435
  }, {
433
- left: rect.width
436
+ left: rect.width,
437
+ right: 0,
438
+ above: 0,
439
+ below: 3
434
440
  });
435
441
  }
436
442
  }
@@ -191,7 +191,12 @@ class ConditionComponent extends _base.BaseComponent {
191
191
  (0, _element.addClass)(label, 'htFiltersMenuLabel');
192
192
  label.textContent = value;
193
193
  wrapper.appendChild(label);
194
- (0, _array.arrayEach)(this.elements, ui => wrapper.appendChild(ui.element));
194
+
195
+ // The SelectUI should not extend the menu width (it should adjust to the menu item width only).
196
+ // That's why it's skipped from rendering when the GhostTable tries to render it.
197
+ if (!wrapper.parentElement.hasAttribute('ghost-table')) {
198
+ (0, _array.arrayEach)(this.elements, ui => wrapper.appendChild(ui.element));
199
+ }
195
200
  return wrapper;
196
201
  }
197
202
  };
@@ -186,7 +186,12 @@ export class ConditionComponent extends BaseComponent {
186
186
  addClass(label, 'htFiltersMenuLabel');
187
187
  label.textContent = value;
188
188
  wrapper.appendChild(label);
189
- arrayEach(this.elements, ui => wrapper.appendChild(ui.element));
189
+
190
+ // The SelectUI should not extend the menu width (it should adjust to the menu item width only).
191
+ // That's why it's skipped from rendering when the GhostTable tries to render it.
192
+ if (!wrapper.parentElement.hasAttribute('ghost-table')) {
193
+ arrayEach(this.elements, ui => wrapper.appendChild(ui.element));
194
+ }
190
195
  return wrapper;
191
196
  }
192
197
  };
@@ -177,7 +177,12 @@ class ValueComponent extends _base.BaseComponent {
177
177
  (0, _element.addClass)(label, 'htFiltersMenuLabel');
178
178
  label.textContent = value;
179
179
  wrapper.appendChild(label);
180
- (0, _array.arrayEach)(this.elements, ui => wrapper.appendChild(ui.element));
180
+
181
+ // The MultipleSelectUI should not extend the menu width (it should adjust to the menu item width only).
182
+ // That's why it's skipped from rendering when the GhostTable tries to render it.
183
+ if (!wrapper.parentElement.hasAttribute('ghost-table')) {
184
+ (0, _array.arrayEach)(this.elements, ui => wrapper.appendChild(ui.element));
185
+ }
181
186
  return wrapper;
182
187
  }
183
188
  };
@@ -172,7 +172,12 @@ export class ValueComponent extends BaseComponent {
172
172
  addClass(label, 'htFiltersMenuLabel');
173
173
  label.textContent = value;
174
174
  wrapper.appendChild(label);
175
- arrayEach(this.elements, ui => wrapper.appendChild(ui.element));
175
+
176
+ // The MultipleSelectUI should not extend the menu width (it should adjust to the menu item width only).
177
+ // That's why it's skipped from rendering when the GhostTable tries to render it.
178
+ if (!wrapper.parentElement.hasAttribute('ghost-table')) {
179
+ arrayEach(this.elements, ui => wrapper.appendChild(ui.element));
180
+ }
176
181
  return wrapper;
177
182
  }
178
183
  };
@@ -5,9 +5,10 @@ import {
5
5
  ColumnConditions,
6
6
  } from './filters';
7
7
 
8
- export type ConditionName = 'begins_with' | 'between' | 'by_value' | 'contains' | 'empty' | 'ends_with' |
9
- 'eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'not_between' | 'not_contains' |
10
- 'not_empty' | 'neq';
8
+ export type ConditionName = 'begins_with' | 'between' | 'by_value' | 'contains' |
9
+ 'date_after' | 'date_before' | 'date_today' | 'date_tomorrow' | 'date_yesterday' |
10
+ 'empty' | 'ends_with' | 'eq' | 'gt' | 'gte' | 'lt' | 'lte' |
11
+ 'not_between' | 'not_contains' | 'not_empty' | 'neq' | 'none';
11
12
 
12
13
  export interface Condition {
13
14
  name: ConditionName;
@@ -45,6 +45,13 @@ class ConditionCollection {
45
45
  * @type {LinkedPhysicalIndexToValueMap}
46
46
  */
47
47
  _defineProperty(this, "filteringStates", new _translations.LinkedPhysicalIndexToValueMap());
48
+ /**
49
+ * Stores the previous state of the condition stack before the latest filter operation.
50
+ * This is used in the `beforeFilter` plugin to allow performing the undo operation.
51
+ *
52
+ * @type {null|Array}
53
+ */
54
+ _defineProperty(this, "previousConditionStack", null);
48
55
  this.hot = hot;
49
56
  this.isMapRegistrable = isMapRegistrable;
50
57
  if (this.isMapRegistrable === true) {
@@ -113,6 +120,13 @@ class ConditionCollection {
113
120
  const localeForColumn = this.hot.getCellMeta(0, column).locale;
114
121
  const args = (0, _array.arrayMap)(conditionDefinition.args, v => typeof v === 'string' ? v.toLocaleLowerCase(localeForColumn) : v);
115
122
  const name = conditionDefinition.name || conditionDefinition.command.key;
123
+
124
+ // If there's no previous condition stack defined (which means the condition stack was not cleared after the
125
+ // previous filter operation or that there was no filter operation performed yet), store the current conditions as
126
+ // the previous condition stack.
127
+ if (this.previousConditionStack === null) {
128
+ this.setPreviousConditionStack(this.exportAllConditions());
129
+ }
116
130
  this.runLocalHooks('beforeAdd', column);
117
131
  const columnType = this.getOperation(column);
118
132
  if (columnType) {
@@ -241,6 +255,8 @@ class ConditionCollection {
241
255
  * @fires ConditionCollection#afterRemove
242
256
  */
243
257
  removeConditions(column) {
258
+ // Store the current conditions as the previous condition stack before it's cleared.
259
+ this.setPreviousConditionStack(this.exportAllConditions());
244
260
  this.runLocalHooks('beforeRemove', column);
245
261
  this.filteringStates.clearValue(column);
246
262
  this.runLocalHooks('afterRemove', column);
@@ -274,6 +290,16 @@ class ConditionCollection {
274
290
  return conditions.length > 0;
275
291
  }
276
292
 
293
+ /**
294
+ * Updates the `previousConditionStack` property with the provided stack.
295
+ * It is used to store the current conditions before they are modified, allowing for undo operations.
296
+ *
297
+ * @param {Array|null} previousConditionStack The stack of previous conditions.
298
+ */
299
+ setPreviousConditionStack(previousConditionStack) {
300
+ this.previousConditionStack = previousConditionStack;
301
+ }
302
+
277
303
  /**
278
304
  * Destroy object.
279
305
  */