handsontable 15.1.0-next-7652ed7-20250219 → 15.2.0-next-8670a33-20250312

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 (161) hide show
  1. package/3rdparty/walkontable/src/selection/border/border.js +16 -3
  2. package/3rdparty/walkontable/src/selection/border/border.mjs +17 -4
  3. package/3rdparty/walkontable/src/selection/scanner.js +1 -1
  4. package/3rdparty/walkontable/src/selection/scanner.mjs +2 -2
  5. package/3rdparty/walkontable/src/table.js +3 -2
  6. package/3rdparty/walkontable/src/table.mjs +4 -3
  7. package/3rdparty/walkontable/src/utils/orderView/viewDiffer/viewOrder.js +1 -0
  8. package/3rdparty/walkontable/src/utils/orderView/viewDiffer/viewOrder.mjs +1 -0
  9. package/3rdparty/walkontable/src/viewport.js +30 -3
  10. package/3rdparty/walkontable/src/viewport.mjs +30 -3
  11. package/CHANGELOG.md +40 -0
  12. package/base.js +2 -2
  13. package/base.mjs +2 -2
  14. package/core.js +2 -37
  15. package/core.mjs +2 -37
  16. package/dataMap/dataMap.js +4 -12
  17. package/dataMap/dataMap.mjs +4 -12
  18. package/dataMap/dataSource.js +2 -2
  19. package/dataMap/dataSource.mjs +2 -2
  20. package/dataMap/metaManager/metaSchema.js +2 -2
  21. package/dataMap/metaManager/metaSchema.mjs +2 -2
  22. package/dist/handsontable.css +2 -2
  23. package/dist/handsontable.full.css +2 -2
  24. package/dist/handsontable.full.js +494 -400
  25. package/dist/handsontable.full.min.css +2 -2
  26. package/dist/handsontable.full.min.js +73 -73
  27. package/dist/handsontable.js +494 -400
  28. package/dist/handsontable.min.css +2 -2
  29. package/dist/handsontable.min.js +43 -43
  30. package/dist/languages/all.js +139 -28
  31. package/dist/languages/all.min.js +1 -1
  32. package/dist/languages/fa-IR.js +167 -0
  33. package/dist/languages/fa-IR.min.js +1 -0
  34. package/dist/languages/it-IT.js +3 -0
  35. package/dist/languages/it-IT.min.js +1 -1
  36. package/dist/languages/sr-SP.js +3 -0
  37. package/dist/languages/sr-SP.min.js +1 -1
  38. package/editors/autocompleteEditor/autocompleteEditor.js +25 -20
  39. package/editors/autocompleteEditor/autocompleteEditor.mjs +25 -20
  40. package/editors/dateEditor/dateEditor.d.ts +0 -2
  41. package/editors/dateEditor/dateEditor.js +18 -7
  42. package/editors/dateEditor/dateEditor.mjs +17 -6
  43. package/focusManager.js +5 -3
  44. package/focusManager.mjs +6 -4
  45. package/helpers/dom/element.d.ts +1 -0
  46. package/helpers/dom/element.js +21 -2
  47. package/helpers/dom/element.mjs +20 -2
  48. package/helpers/dom/event.js +2 -1
  49. package/helpers/dom/event.mjs +2 -1
  50. package/helpers/mixed.js +2 -2
  51. package/helpers/mixed.mjs +2 -2
  52. package/helpers/number.js +1 -0
  53. package/helpers/number.mjs +1 -0
  54. package/i18n/languages/fa-IR.d.ts +5 -0
  55. package/i18n/languages/fa-IR.js +96 -0
  56. package/i18n/languages/fa-IR.mjs +90 -0
  57. package/i18n/languages/index.d.ts +2 -0
  58. package/i18n/languages/index.js +2 -0
  59. package/i18n/languages/index.mjs +2 -1
  60. package/i18n/languages/it-IT.js +3 -0
  61. package/i18n/languages/it-IT.mjs +3 -0
  62. package/i18n/languages/sr-SP.js +3 -0
  63. package/i18n/languages/sr-SP.mjs +3 -0
  64. package/i18n/phraseFormatters/substituteVariables.js +1 -0
  65. package/i18n/phraseFormatters/substituteVariables.mjs +1 -0
  66. package/languages/all.js +139 -28
  67. package/languages/fa-IR.js +167 -0
  68. package/languages/fa-IR.mjs +92 -0
  69. package/languages/index.js +139 -28
  70. package/languages/index.mjs +2 -1
  71. package/languages/it-IT.js +3 -0
  72. package/languages/it-IT.mjs +3 -0
  73. package/languages/sr-SP.js +3 -0
  74. package/languages/sr-SP.mjs +3 -0
  75. package/package.json +13 -2
  76. package/plugins/columnSorting/columnSorting.js +17 -1
  77. package/plugins/columnSorting/columnSorting.mjs +18 -2
  78. package/plugins/columnSorting/columnStatesManager.js +1 -0
  79. package/plugins/columnSorting/columnStatesManager.mjs +1 -0
  80. package/plugins/columnSorting/utils.js +14 -0
  81. package/plugins/columnSorting/utils.mjs +13 -0
  82. package/plugins/comments/comments.js +5 -2
  83. package/plugins/comments/comments.mjs +6 -3
  84. package/plugins/contextMenu/menu/menu.js +9 -3
  85. package/plugins/contextMenu/menu/menu.mjs +9 -3
  86. package/plugins/contextMenu/predefinedItems/columnLeft.js +3 -8
  87. package/plugins/contextMenu/predefinedItems/columnLeft.mjs +3 -8
  88. package/plugins/contextMenu/predefinedItems/columnRight.js +2 -9
  89. package/plugins/contextMenu/predefinedItems/columnRight.mjs +2 -9
  90. package/plugins/contextMenu/predefinedItems/rowAbove.js +3 -8
  91. package/plugins/contextMenu/predefinedItems/rowAbove.mjs +3 -8
  92. package/plugins/contextMenu/predefinedItems/rowBelow.js +2 -9
  93. package/plugins/contextMenu/predefinedItems/rowBelow.mjs +2 -9
  94. package/plugins/copyPaste/copyPaste.js +3 -3
  95. package/plugins/copyPaste/copyPaste.mjs +4 -4
  96. package/plugins/exportFile/types/csv.js +1 -0
  97. package/plugins/exportFile/types/csv.mjs +1 -0
  98. package/plugins/filters/conditionCollection.js +0 -26
  99. package/plugins/filters/conditionCollection.mjs +0 -26
  100. package/plugins/filters/filters.d.ts +2 -0
  101. package/plugins/filters/filters.js +77 -8
  102. package/plugins/filters/filters.mjs +77 -8
  103. package/plugins/mergeCells/mergeCells.js +9 -6
  104. package/plugins/mergeCells/mergeCells.mjs +9 -6
  105. package/plugins/multiColumnSorting/multiColumnSorting.js +1 -21
  106. package/plugins/multiColumnSorting/multiColumnSorting.mjs +1 -21
  107. package/plugins/nestedHeaders/nestedHeaders.js +5 -3
  108. package/plugins/nestedHeaders/nestedHeaders.mjs +5 -3
  109. package/plugins/nestedHeaders/stateManager/index.js +1 -0
  110. package/plugins/nestedHeaders/stateManager/index.mjs +1 -0
  111. package/plugins/undoRedo/actions/_base.js +10 -0
  112. package/plugins/undoRedo/actions/_base.mjs +10 -0
  113. package/plugins/undoRedo/actions/cellAlignment.js +1 -1
  114. package/plugins/undoRedo/actions/cellAlignment.mjs +1 -1
  115. package/plugins/undoRedo/actions/columnMove.js +1 -1
  116. package/plugins/undoRedo/actions/columnMove.mjs +1 -1
  117. package/plugins/undoRedo/actions/columnSort.js +1 -1
  118. package/plugins/undoRedo/actions/columnSort.mjs +1 -1
  119. package/plugins/undoRedo/actions/createColumn.js +1 -1
  120. package/plugins/undoRedo/actions/createColumn.mjs +1 -1
  121. package/plugins/undoRedo/actions/createRow.js +1 -1
  122. package/plugins/undoRedo/actions/createRow.mjs +1 -1
  123. package/plugins/undoRedo/actions/dataChange.js +1 -1
  124. package/plugins/undoRedo/actions/dataChange.mjs +1 -1
  125. package/plugins/undoRedo/actions/filters.js +3 -3
  126. package/plugins/undoRedo/actions/filters.mjs +3 -3
  127. package/plugins/undoRedo/actions/mergeCells.js +4 -1
  128. package/plugins/undoRedo/actions/mergeCells.mjs +4 -1
  129. package/plugins/undoRedo/actions/removeColumn.js +4 -2
  130. package/plugins/undoRedo/actions/removeColumn.mjs +4 -2
  131. package/plugins/undoRedo/actions/removeRow.js +1 -1
  132. package/plugins/undoRedo/actions/removeRow.mjs +1 -1
  133. package/plugins/undoRedo/actions/rowMove.js +1 -1
  134. package/plugins/undoRedo/actions/rowMove.mjs +1 -1
  135. package/plugins/undoRedo/actions/unmergeCells.js +4 -1
  136. package/plugins/undoRedo/actions/unmergeCells.mjs +4 -1
  137. package/plugins/undoRedo/undoRedo.d.ts +48 -17
  138. package/renderers/checkboxRenderer/checkboxRenderer.js +1 -1
  139. package/renderers/checkboxRenderer/checkboxRenderer.mjs +2 -2
  140. package/renderers/numericRenderer/numericRenderer.js +10 -2
  141. package/renderers/numericRenderer/numericRenderer.mjs +10 -2
  142. package/renderers/textRenderer/textRenderer.js +3 -12
  143. package/renderers/textRenderer/textRenderer.mjs +4 -13
  144. package/shortcuts/utils.js +1 -0
  145. package/shortcuts/utils.mjs +1 -0
  146. package/styles/handsontable.css +83 -99
  147. package/styles/handsontable.min.css +3 -3
  148. package/styles/ht-theme-horizon.css +14 -2
  149. package/styles/ht-theme-horizon.min.css +3 -3
  150. package/styles/ht-theme-main.css +14 -2
  151. package/styles/ht-theme-main.min.css +3 -3
  152. package/tableView.js +9 -0
  153. package/tableView.mjs +9 -0
  154. package/translations/maps/linkedPhysicalIndexToValueMap.js +1 -0
  155. package/translations/maps/linkedPhysicalIndexToValueMap.mjs +1 -0
  156. package/translations/maps/utils/physicallyIndexed.js +1 -0
  157. package/translations/maps/utils/physicallyIndexed.mjs +1 -0
  158. package/utils/dataStructures/priorityMap.js +1 -0
  159. package/utils/dataStructures/priorityMap.mjs +1 -0
  160. package/plugins/multiColumnSorting/utils.js +0 -13
  161. package/plugins/multiColumnSorting/utils.mjs +0 -9
@@ -303,7 +303,6 @@ class Menu {
303
303
  this.openSubMenu(coords.row);
304
304
  }
305
305
  },
306
- rowHeights: row => filteredItems[row].name === _predefinedItems.SEPARATOR ? 1 : undefined,
307
306
  afterOnCellContextMenu: event => {
308
307
  event.preventDefault();
309
308
 
@@ -574,6 +573,7 @@ class Menu {
574
573
  * and adjusts the width and height of the menu's holder and hider elements accordingly.
575
574
  */
576
575
  updateMenuDimensions() {
576
+ const stylesHandler = this.hotMenu.view.getStylesHandler();
577
577
  const {
578
578
  wtTable
579
579
  } = this.hotMenu.view._wt;
@@ -586,8 +586,14 @@ class Menu {
586
586
  const currentRowHeight = itemCell ? (0, _element.outerHeight)(this.hotMenu.getCell(index, 0)) : 0;
587
587
  return accumulator + (value.name === _predefinedItems.SEPARATOR ? 1 : currentRowHeight);
588
588
  }, 0);
589
- holderStyle.width = `${currentHiderWidth}px`;
590
- holderStyle.height = `${realHeight}px`;
589
+ if (stylesHandler.isClassicTheme()) {
590
+ // Additional 3px to menu's size because of additional border around its `table.htCore`.
591
+ holderStyle.width = `${currentHiderWidth + 3}px`;
592
+ holderStyle.height = `${realHeight + 3}px`;
593
+ } else {
594
+ holderStyle.width = `${currentHiderWidth}px`;
595
+ holderStyle.height = `${realHeight}px`;
596
+ }
591
597
  hiderStyle.height = holderStyle.height;
592
598
  }
593
599
 
@@ -299,7 +299,6 @@ export class Menu {
299
299
  this.openSubMenu(coords.row);
300
300
  }
301
301
  },
302
- rowHeights: row => filteredItems[row].name === SEPARATOR ? 1 : undefined,
303
302
  afterOnCellContextMenu: event => {
304
303
  event.preventDefault();
305
304
 
@@ -570,6 +569,7 @@ export class Menu {
570
569
  * and adjusts the width and height of the menu's holder and hider elements accordingly.
571
570
  */
572
571
  updateMenuDimensions() {
572
+ const stylesHandler = this.hotMenu.view.getStylesHandler();
573
573
  const {
574
574
  wtTable
575
575
  } = this.hotMenu.view._wt;
@@ -582,8 +582,14 @@ export class Menu {
582
582
  const currentRowHeight = itemCell ? outerHeight(this.hotMenu.getCell(index, 0)) : 0;
583
583
  return accumulator + (value.name === SEPARATOR ? 1 : currentRowHeight);
584
584
  }, 0);
585
- holderStyle.width = `${currentHiderWidth}px`;
586
- holderStyle.height = `${realHeight}px`;
585
+ if (stylesHandler.isClassicTheme()) {
586
+ // Additional 3px to menu's size because of additional border around its `table.htCore`.
587
+ holderStyle.width = `${currentHiderWidth + 3}px`;
588
+ holderStyle.height = `${realHeight + 3}px`;
589
+ } else {
590
+ holderStyle.width = `${currentHiderWidth}px`;
591
+ holderStyle.height = `${realHeight}px`;
592
+ }
587
593
  hiderStyle.height = holderStyle.height;
588
594
  }
589
595
 
@@ -26,19 +26,14 @@ function columnLeftItem() {
26
26
  return true;
27
27
  }
28
28
  const range = this.getSelectedRangeLast();
29
- if (!range) {
30
- return true;
31
- }
32
- if (range.isSingleHeader() && range.highlight.col < 0) {
29
+ if (!range || this.selection.isSelectedByRowHeader() || range.isSingleHeader() && range.highlight.col < 0 || this.countSourceCols() >= this.getSettings().maxCols) {
33
30
  return true;
34
31
  }
35
32
  if (this.selection.isSelectedByCorner()) {
36
- const totalColumns = this.countCols();
37
-
38
33
  // Enable "Insert column left" only when there is at least one column.
39
- return totalColumns === 0;
34
+ return this.countCols() === 0;
40
35
  }
41
- return this.selection.isSelectedByRowHeader() || this.countCols() >= this.getSettings().maxCols;
36
+ return false;
42
37
  },
43
38
  hidden() {
44
39
  return !this.getSettings().allowInsertColumn;
@@ -20,19 +20,14 @@ export default function columnLeftItem() {
20
20
  return true;
21
21
  }
22
22
  const range = this.getSelectedRangeLast();
23
- if (!range) {
24
- return true;
25
- }
26
- if (range.isSingleHeader() && range.highlight.col < 0) {
23
+ if (!range || this.selection.isSelectedByRowHeader() || range.isSingleHeader() && range.highlight.col < 0 || this.countSourceCols() >= this.getSettings().maxCols) {
27
24
  return true;
28
25
  }
29
26
  if (this.selection.isSelectedByCorner()) {
30
- const totalColumns = this.countCols();
31
-
32
27
  // Enable "Insert column left" only when there is at least one column.
33
- return totalColumns === 0;
28
+ return this.countCols() === 0;
34
29
  }
35
- return this.selection.isSelectedByRowHeader() || this.countCols() >= this.getSettings().maxCols;
30
+ return false;
36
31
  },
37
32
  hidden() {
38
33
  return !this.getSettings().allowInsertColumn;
@@ -26,17 +26,10 @@ function columnRightItem() {
26
26
  return true;
27
27
  }
28
28
  const range = this.getSelectedRangeLast();
29
- if (!range) {
29
+ if (!range || this.selection.isSelectedByRowHeader() || range.isSingleHeader() && range.highlight.col < 0 || this.countSourceCols() >= this.getSettings().maxCols) {
30
30
  return true;
31
31
  }
32
- if (range.isSingleHeader() && range.highlight.col < 0) {
33
- return true;
34
- }
35
- if (this.selection.isSelectedByCorner()) {
36
- // Enable "Insert column right" always when the menu is triggered by corner click.
37
- return false;
38
- }
39
- return this.selection.isSelectedByRowHeader() || this.countCols() >= this.getSettings().maxCols;
32
+ return false;
40
33
  },
41
34
  hidden() {
42
35
  return !this.getSettings().allowInsertColumn;
@@ -20,17 +20,10 @@ export default function columnRightItem() {
20
20
  return true;
21
21
  }
22
22
  const range = this.getSelectedRangeLast();
23
- if (!range) {
23
+ if (!range || this.selection.isSelectedByRowHeader() || range.isSingleHeader() && range.highlight.col < 0 || this.countSourceCols() >= this.getSettings().maxCols) {
24
24
  return true;
25
25
  }
26
- if (range.isSingleHeader() && range.highlight.col < 0) {
27
- return true;
28
- }
29
- if (this.selection.isSelectedByCorner()) {
30
- // Enable "Insert column right" always when the menu is triggered by corner click.
31
- return false;
32
- }
33
- return this.selection.isSelectedByRowHeader() || this.countCols() >= this.getSettings().maxCols;
26
+ return false;
34
27
  },
35
28
  hidden() {
36
29
  return !this.getSettings().allowInsertColumn;
@@ -22,19 +22,14 @@ function rowAboveItem() {
22
22
  },
23
23
  disabled() {
24
24
  const range = this.getSelectedRangeLast();
25
- if (!range) {
26
- return true;
27
- }
28
- if (range.isSingleHeader() && range.highlight.row < 0) {
25
+ if (!range || this.selection.isSelectedByColumnHeader() || range.isSingleHeader() && range.highlight.row < 0 || this.countSourceRows() >= this.getSettings().maxRows) {
29
26
  return true;
30
27
  }
31
28
  if (this.selection.isSelectedByCorner()) {
32
- const totalRows = this.countRows();
33
-
34
29
  // Enable "Insert row above" only when there is at least one row.
35
- return totalRows === 0;
30
+ return this.countRows() === 0;
36
31
  }
37
- return this.selection.isSelectedByColumnHeader() || this.countRows() >= this.getSettings().maxRows;
32
+ return false;
38
33
  },
39
34
  hidden() {
40
35
  return !this.getSettings().allowInsertRow;
@@ -16,19 +16,14 @@ export default function rowAboveItem() {
16
16
  },
17
17
  disabled() {
18
18
  const range = this.getSelectedRangeLast();
19
- if (!range) {
20
- return true;
21
- }
22
- if (range.isSingleHeader() && range.highlight.row < 0) {
19
+ if (!range || this.selection.isSelectedByColumnHeader() || range.isSingleHeader() && range.highlight.row < 0 || this.countSourceRows() >= this.getSettings().maxRows) {
23
20
  return true;
24
21
  }
25
22
  if (this.selection.isSelectedByCorner()) {
26
- const totalRows = this.countRows();
27
-
28
23
  // Enable "Insert row above" only when there is at least one row.
29
- return totalRows === 0;
24
+ return this.countRows() === 0;
30
25
  }
31
- return this.selection.isSelectedByColumnHeader() || this.countRows() >= this.getSettings().maxRows;
26
+ return false;
32
27
  },
33
28
  hidden() {
34
29
  return !this.getSettings().allowInsertRow;
@@ -22,17 +22,10 @@ function rowBelowItem() {
22
22
  },
23
23
  disabled() {
24
24
  const range = this.getSelectedRangeLast();
25
- if (!range) {
25
+ if (!range || this.selection.isSelectedByColumnHeader() || range.isSingleHeader() && range.highlight.row < 0 || this.countSourceRows() >= this.getSettings().maxRows) {
26
26
  return true;
27
27
  }
28
- if (range.isSingleHeader() && range.highlight.row < 0) {
29
- return true;
30
- }
31
- if (this.selection.isSelectedByCorner()) {
32
- // Enable "Insert row below" always when the menu is triggered by corner click.
33
- return false;
34
- }
35
- return this.selection.isSelectedByColumnHeader() || this.countRows() >= this.getSettings().maxRows;
28
+ return false;
36
29
  },
37
30
  hidden() {
38
31
  return !this.getSettings().allowInsertRow;
@@ -16,17 +16,10 @@ export default function rowBelowItem() {
16
16
  },
17
17
  disabled() {
18
18
  const range = this.getSelectedRangeLast();
19
- if (!range) {
19
+ if (!range || this.selection.isSelectedByColumnHeader() || range.isSingleHeader() && range.highlight.row < 0 || this.countSourceRows() >= this.getSettings().maxRows) {
20
20
  return true;
21
21
  }
22
- if (range.isSingleHeader() && range.highlight.row < 0) {
23
- return true;
24
- }
25
- if (this.selection.isSelectedByCorner()) {
26
- // Enable "Insert row below" always when the menu is triggered by corner click.
27
- return false;
28
- }
29
- return this.selection.isSelectedByColumnHeader() || this.countRows() >= this.getSettings().maxRows;
22
+ return false;
30
23
  },
31
24
  hidden() {
32
25
  return !this.getSettings().allowInsertRow;
@@ -567,7 +567,7 @@ class CopyPaste extends _base.BasePlugin {
567
567
  const isHotInput = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.hasAttribute('data-hot-input');
568
568
  const selectedCell = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
569
569
  const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
570
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
570
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || (0, _element.isHTMLElement)(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
571
571
  return;
572
572
  }
573
573
  event.preventDefault();
@@ -602,7 +602,7 @@ class CopyPaste extends _base.BasePlugin {
602
602
  const isHotInput = (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.hasAttribute('data-hot-input');
603
603
  const selectedCell = (_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.highlight;
604
604
  const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
605
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
605
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || (0, _element.isHTMLElement)(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
606
606
  return;
607
607
  }
608
608
  event.preventDefault();
@@ -636,7 +636,7 @@ class CopyPaste extends _base.BasePlugin {
636
636
  const isHotInput = (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.hasAttribute('data-hot-input');
637
637
  const selectedCell = (_this$hot$getSelected3 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected3 === void 0 ? void 0 : _this$hot$getSelected3.highlight;
638
638
  const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
639
- if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
639
+ if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || (0, _element.isHTMLElement)(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
640
640
  return;
641
641
  }
642
642
  event.preventDefault();
@@ -17,7 +17,7 @@ import { Hooks } from "../../core/hooks/index.mjs";
17
17
  import { stringify, parse } from "../../3rdparty/SheetClip/index.mjs";
18
18
  import { arrayEach } from "../../helpers/array.mjs";
19
19
  import { sanitize } from "../../helpers/string.mjs";
20
- import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent } from "../../helpers/dom/element.mjs";
20
+ import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent, isHTMLElement } from "../../helpers/dom/element.mjs";
21
21
  import { isSafari } from "../../helpers/browser.mjs";
22
22
  import copyItem from "./contextMenuItem/copy.mjs";
23
23
  import copyColumnHeadersOnlyItem from "./contextMenuItem/copyColumnHeadersOnly.mjs";
@@ -563,7 +563,7 @@ export class CopyPaste extends BasePlugin {
563
563
  const isHotInput = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.hasAttribute('data-hot-input');
564
564
  const selectedCell = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
565
565
  const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
566
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
566
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
567
567
  return;
568
568
  }
569
569
  event.preventDefault();
@@ -598,7 +598,7 @@ export class CopyPaste extends BasePlugin {
598
598
  const isHotInput = (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.hasAttribute('data-hot-input');
599
599
  const selectedCell = (_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.highlight;
600
600
  const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
601
- if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
601
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
602
602
  return;
603
603
  }
604
604
  event.preventDefault();
@@ -632,7 +632,7 @@ export class CopyPaste extends BasePlugin {
632
632
  const isHotInput = (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.hasAttribute('data-hot-input');
633
633
  const selectedCell = (_this$hot$getSelected3 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected3 === void 0 ? void 0 : _this$hot$getSelected3.highlight;
634
634
  const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
635
- if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || event.target instanceof HTMLElement && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
635
+ if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
636
636
  return;
637
637
  }
638
638
  event.preventDefault();
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
+ require("core-js/modules/esnext.iterator.constructor.js");
4
5
  require("core-js/modules/esnext.iterator.map.js");
5
6
  var _array = require("../../../helpers/array");
6
7
  var _mixed = require("../../../helpers/mixed");
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import { arrayEach, arrayMap } from "../../../helpers/array.mjs";
3
4
  import { stringify } from "../../../helpers/mixed.mjs";
@@ -49,13 +49,6 @@ class ConditionCollection {
49
49
  * @type {LinkedPhysicalIndexToValueMap}
50
50
  */
51
51
  _defineProperty(this, "filteringStates", new _translations.LinkedPhysicalIndexToValueMap());
52
- /**
53
- * Stores the previous state of the condition stack before the latest filter operation.
54
- * This is used in the `beforeFilter` plugin to allow performing the undo operation.
55
- *
56
- * @type {null|Array}
57
- */
58
- _defineProperty(this, "previousConditionStack", null);
59
52
  this.hot = hot;
60
53
  this.isMapRegistrable = isMapRegistrable;
61
54
  if (this.isMapRegistrable === true) {
@@ -124,13 +117,6 @@ class ConditionCollection {
124
117
  const localeForColumn = this.hot.getCellMeta(0, column).locale;
125
118
  const args = conditionDefinition.args.map(v => typeof v === 'string' ? v.toLocaleLowerCase(localeForColumn) : v);
126
119
  const name = conditionDefinition.name || conditionDefinition.command.key;
127
-
128
- // If there's no previous condition stack defined (which means the condition stack was not cleared after the
129
- // previous filter operation or that there was no filter operation performed yet), store the current conditions as
130
- // the previous condition stack.
131
- if (this.previousConditionStack === null) {
132
- this.setPreviousConditionStack(this.exportAllConditions());
133
- }
134
120
  this.runLocalHooks('beforeAdd', column);
135
121
  const columnType = this.getOperation(column);
136
122
  if (columnType) {
@@ -259,8 +245,6 @@ class ConditionCollection {
259
245
  * @fires ConditionCollection#afterRemove
260
246
  */
261
247
  removeConditions(column) {
262
- // Store the current conditions as the previous condition stack before it's cleared.
263
- this.setPreviousConditionStack(this.exportAllConditions());
264
248
  this.runLocalHooks('beforeRemove', column);
265
249
  this.filteringStates.clearValue(column);
266
250
  this.runLocalHooks('afterRemove', column);
@@ -294,16 +278,6 @@ class ConditionCollection {
294
278
  return conditions.length > 0;
295
279
  }
296
280
 
297
- /**
298
- * Updates the `previousConditionStack` property with the provided stack.
299
- * It is used to store the current conditions before they are modified, allowing for undo operations.
300
- *
301
- * @param {Array|null} previousConditionStack The stack of previous conditions.
302
- */
303
- setPreviousConditionStack(previousConditionStack) {
304
- this.previousConditionStack = previousConditionStack;
305
- }
306
-
307
281
  /**
308
282
  * Destroy object.
309
283
  */
@@ -45,13 +45,6 @@ class ConditionCollection {
45
45
  * @type {LinkedPhysicalIndexToValueMap}
46
46
  */
47
47
  _defineProperty(this, "filteringStates", new IndexToValueMap());
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);
55
48
  this.hot = hot;
56
49
  this.isMapRegistrable = isMapRegistrable;
57
50
  if (this.isMapRegistrable === true) {
@@ -120,13 +113,6 @@ class ConditionCollection {
120
113
  const localeForColumn = this.hot.getCellMeta(0, column).locale;
121
114
  const args = conditionDefinition.args.map(v => typeof v === 'string' ? v.toLocaleLowerCase(localeForColumn) : v);
122
115
  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
- }
130
116
  this.runLocalHooks('beforeAdd', column);
131
117
  const columnType = this.getOperation(column);
132
118
  if (columnType) {
@@ -255,8 +241,6 @@ class ConditionCollection {
255
241
  * @fires ConditionCollection#afterRemove
256
242
  */
257
243
  removeConditions(column) {
258
- // Store the current conditions as the previous condition stack before it's cleared.
259
- this.setPreviousConditionStack(this.exportAllConditions());
260
244
  this.runLocalHooks('beforeRemove', column);
261
245
  this.filteringStates.clearValue(column);
262
246
  this.runLocalHooks('afterRemove', column);
@@ -290,16 +274,6 @@ class ConditionCollection {
290
274
  return conditions.length > 0;
291
275
  }
292
276
 
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
-
303
277
  /**
304
278
  * Destroy object.
305
279
  */
@@ -48,6 +48,8 @@ export declare class Filters extends BasePlugin {
48
48
  addCondition(column: number, name: string, args: any[], operationId?: OperationType): void;
49
49
  removeConditions(column: number): void;
50
50
  clearConditions(column?: number): void;
51
+ importConditions(conditions: ColumnConditions[]): void;
52
+ exportConditions(): ColumnConditions[];
51
53
  filter(): void;
52
54
  getSelectedColumn(): { physicalIndex: number, visualIndex: number } | null;
53
55
  getDataMapAtColumn(column?: number): CellLikeData[];
@@ -81,6 +81,7 @@ const SHORTCUTS_GROUP = PLUGIN_KEY;
81
81
  */
82
82
  var _menuFocusNavigator = /*#__PURE__*/new WeakMap();
83
83
  var _dropdownMenuTraces = /*#__PURE__*/new WeakMap();
84
+ var _previousConditionStack = /*#__PURE__*/new WeakMap();
84
85
  var _Filters_brand = /*#__PURE__*/new WeakSet();
85
86
  class Filters extends _base.BasePlugin {
86
87
  static get PLUGIN_KEY() {
@@ -152,6 +153,13 @@ class Filters extends _base.BasePlugin {
152
153
  * @type {WeakSet<Menu>}
153
154
  */
154
155
  _classPrivateFieldInitSpec(this, _dropdownMenuTraces, new WeakSet());
156
+ /**
157
+ * Stores the previous state of the condition stack before the latest filter operation.
158
+ * This is used in the `beforeFilter` plugin to allow performing the undo operation.
159
+ *
160
+ * @type {Array}
161
+ */
162
+ _classPrivateFieldInitSpec(this, _previousConditionStack, []);
155
163
  this.hot.addHook('afterGetColHeader', function () {
156
164
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
157
165
  args[_key] = arguments[_key];
@@ -494,6 +502,51 @@ class Filters extends _base.BasePlugin {
494
502
  }
495
503
  }
496
504
 
505
+ /**
506
+ * Imports filter conditions to all columns to the plugin. The method accepts
507
+ * the array of conditions with the same structure as the {@link Filters#exportConditions} method returns.
508
+ * Importing conditions will replace the current conditions. Once replaced, the state of the condition
509
+ * will be reflected in the UI. To apply the changes and filter the table, call
510
+ * the {@link Filters#filter} method eventually.
511
+ *
512
+ * @param {Array} conditions Array of conditions.
513
+ */
514
+ importConditions(conditions) {
515
+ this.conditionCollection.importAllConditions(conditions);
516
+ }
517
+
518
+ /* eslint-disable jsdoc/require-description-complete-sentence */
519
+ /**
520
+ * Exports filter conditions for all columns from the plugin.
521
+ * The array represents the filter state for each column. For example:
522
+ *
523
+ * ```js
524
+ * [
525
+ * {
526
+ * column: 1,
527
+ * operation: 'conjunction',
528
+ * conditions: [
529
+ * { name: 'gt', args: [95] },
530
+ * ]
531
+ * },
532
+ * {
533
+ * column: 7,
534
+ * operation: 'conjunction',
535
+ * conditions: [
536
+ * { name: 'contains', args: ['mike'] },
537
+ * { name: 'begins_with', args: ['m'] },
538
+ * ]
539
+ * },
540
+ * ]
541
+ * ```
542
+ *
543
+ * @returns {Array}
544
+ */
545
+ /* eslint-enable jsdoc/require-description-complete-sentence */
546
+ exportConditions() {
547
+ return this.conditionCollection.exportAllConditions();
548
+ }
549
+
497
550
  /**
498
551
  * Filters data based on added filter conditions.
499
552
  *
@@ -507,8 +560,8 @@ class Filters extends _base.BasePlugin {
507
560
  const dataFilter = this._createDataFilter();
508
561
  const needToFilter = !this.conditionCollection.isEmpty();
509
562
  let visibleVisualRows = [];
510
- const conditions = this.conditionCollection.exportAllConditions();
511
- const allowFiltering = this.hot.runHooks('beforeFilter', conditions, this.conditionCollection.previousConditionStack);
563
+ const conditions = this.exportConditions();
564
+ const allowFiltering = this.hot.runHooks('beforeFilter', conditions, _classPrivateFieldGet(_previousConditionStack, this));
512
565
  if (allowFiltering !== false) {
513
566
  if (needToFilter) {
514
567
  const trimmedRows = [];
@@ -531,11 +584,13 @@ class Filters extends _base.BasePlugin {
531
584
  } else {
532
585
  this.filtersRowsMap.clear();
533
586
  }
587
+ _classPrivateFieldSet(_previousConditionStack, this, this.exportConditions());
588
+ this.hot.runHooks('afterFilter', conditions);
589
+ this.hot.view.adjustElementsSize();
590
+ this.hot.render();
591
+ } else {
592
+ this.importConditions(_classPrivateFieldGet(_previousConditionStack, this));
534
593
  }
535
- this.hot.runHooks('afterFilter', conditions);
536
- this.conditionCollection.setPreviousConditionStack(null);
537
- this.hot.view.adjustElementsSize();
538
- this.hot.render();
539
594
  if (this.hot.selection.isSelected()) {
540
595
  this.hot.selectCell(navigableHeaders ? -1 : 0, this.hot.getSelectedRangeLast().highlight.col);
541
596
  }
@@ -898,7 +953,6 @@ function _onActionBarSubmit(submitType) {
898
953
  }
899
954
  this.conditionUpdateObserver.flush();
900
955
  this.components.forEach(component => component.saveState(physicalIndex));
901
- this.filtersRowsMap.clear();
902
956
  this.filter();
903
957
  }
904
958
  (_this$dropdownMenuPlu3 = this.dropdownMenuPlugin) === null || _this$dropdownMenuPlu3 === void 0 || _this$dropdownMenuPlu3.close();
@@ -940,8 +994,23 @@ function _updateComponents(conditionsState) {
940
994
  editedConditionStack: {
941
995
  conditions,
942
996
  column
943
- }
997
+ },
998
+ conditionArgsChange
944
999
  } = conditionsState;
1000
+ if (Array.isArray(conditionArgsChange)) {
1001
+ // update the previous condition stack (only for 'by_value' condition) on each dataset
1002
+ // change to make the undo/redo work properly
1003
+ _classPrivateFieldSet(_previousConditionStack, this, _classPrivateFieldGet(_previousConditionStack, this).map(stack => {
1004
+ if (stack.column === column && conditions.length > 0) {
1005
+ stack.conditions.forEach(condition => {
1006
+ if (condition.name === 'by_value') {
1007
+ condition.args = [[...conditionArgsChange]];
1008
+ }
1009
+ });
1010
+ }
1011
+ return stack;
1012
+ }));
1013
+ }
945
1014
  const conditionsByValue = conditions.filter(condition => condition.name === _constants2.CONDITION_BY_VALUE);
946
1015
  const conditionsWithoutByValue = conditions.filter(condition => condition.name !== _constants2.CONDITION_BY_VALUE);
947
1016
  if (conditionsByValue.length >= 2 || conditionsWithoutByValue.length >= 3) {