handsontable 15.1.0 → 15.2.0-next-9a1a15b-20250314

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 (163) 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 +500 -412
  25. package/dist/handsontable.full.min.css +2 -2
  26. package/dist/handsontable.full.min.js +73 -73
  27. package/dist/handsontable.js +500 -412
  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/editors/textEditor/textEditor.js +1 -1
  44. package/editors/textEditor/textEditor.mjs +2 -2
  45. package/focusManager.js +5 -3
  46. package/focusManager.mjs +6 -4
  47. package/helpers/dom/element.d.ts +1 -0
  48. package/helpers/dom/element.js +23 -4
  49. package/helpers/dom/element.mjs +21 -3
  50. package/helpers/dom/event.js +2 -1
  51. package/helpers/dom/event.mjs +2 -1
  52. package/helpers/mixed.js +2 -2
  53. package/helpers/mixed.mjs +2 -2
  54. package/helpers/number.js +1 -0
  55. package/helpers/number.mjs +1 -0
  56. package/i18n/languages/fa-IR.d.ts +5 -0
  57. package/i18n/languages/fa-IR.js +96 -0
  58. package/i18n/languages/fa-IR.mjs +90 -0
  59. package/i18n/languages/index.d.ts +2 -0
  60. package/i18n/languages/index.js +2 -0
  61. package/i18n/languages/index.mjs +2 -1
  62. package/i18n/languages/it-IT.js +3 -0
  63. package/i18n/languages/it-IT.mjs +3 -0
  64. package/i18n/languages/sr-SP.js +3 -0
  65. package/i18n/languages/sr-SP.mjs +3 -0
  66. package/i18n/phraseFormatters/substituteVariables.js +1 -0
  67. package/i18n/phraseFormatters/substituteVariables.mjs +1 -0
  68. package/languages/all.js +139 -28
  69. package/languages/fa-IR.js +167 -0
  70. package/languages/fa-IR.mjs +92 -0
  71. package/languages/index.js +139 -28
  72. package/languages/index.mjs +2 -1
  73. package/languages/it-IT.js +3 -0
  74. package/languages/it-IT.mjs +3 -0
  75. package/languages/sr-SP.js +3 -0
  76. package/languages/sr-SP.mjs +3 -0
  77. package/package.json +13 -2
  78. package/plugins/columnSorting/columnSorting.js +17 -1
  79. package/plugins/columnSorting/columnSorting.mjs +18 -2
  80. package/plugins/columnSorting/columnStatesManager.js +1 -0
  81. package/plugins/columnSorting/columnStatesManager.mjs +1 -0
  82. package/plugins/columnSorting/utils.js +14 -0
  83. package/plugins/columnSorting/utils.mjs +13 -0
  84. package/plugins/comments/comments.js +5 -2
  85. package/plugins/comments/comments.mjs +6 -3
  86. package/plugins/contextMenu/menu/menu.js +9 -3
  87. package/plugins/contextMenu/menu/menu.mjs +9 -3
  88. package/plugins/contextMenu/predefinedItems/columnLeft.js +3 -8
  89. package/plugins/contextMenu/predefinedItems/columnLeft.mjs +3 -8
  90. package/plugins/contextMenu/predefinedItems/columnRight.js +2 -9
  91. package/plugins/contextMenu/predefinedItems/columnRight.mjs +2 -9
  92. package/plugins/contextMenu/predefinedItems/rowAbove.js +3 -8
  93. package/plugins/contextMenu/predefinedItems/rowAbove.mjs +3 -8
  94. package/plugins/contextMenu/predefinedItems/rowBelow.js +2 -9
  95. package/plugins/contextMenu/predefinedItems/rowBelow.mjs +2 -9
  96. package/plugins/copyPaste/copyPaste.js +6 -12
  97. package/plugins/copyPaste/copyPaste.mjs +7 -13
  98. package/plugins/exportFile/types/csv.js +1 -0
  99. package/plugins/exportFile/types/csv.mjs +1 -0
  100. package/plugins/filters/conditionCollection.js +0 -26
  101. package/plugins/filters/conditionCollection.mjs +0 -26
  102. package/plugins/filters/filters.d.ts +2 -0
  103. package/plugins/filters/filters.js +77 -8
  104. package/plugins/filters/filters.mjs +77 -8
  105. package/plugins/mergeCells/mergeCells.js +9 -6
  106. package/plugins/mergeCells/mergeCells.mjs +9 -6
  107. package/plugins/multiColumnSorting/multiColumnSorting.js +1 -21
  108. package/plugins/multiColumnSorting/multiColumnSorting.mjs +1 -21
  109. package/plugins/nestedHeaders/nestedHeaders.js +5 -3
  110. package/plugins/nestedHeaders/nestedHeaders.mjs +5 -3
  111. package/plugins/nestedHeaders/stateManager/index.js +1 -0
  112. package/plugins/nestedHeaders/stateManager/index.mjs +1 -0
  113. package/plugins/undoRedo/actions/_base.js +10 -0
  114. package/plugins/undoRedo/actions/_base.mjs +10 -0
  115. package/plugins/undoRedo/actions/cellAlignment.js +1 -1
  116. package/plugins/undoRedo/actions/cellAlignment.mjs +1 -1
  117. package/plugins/undoRedo/actions/columnMove.js +1 -1
  118. package/plugins/undoRedo/actions/columnMove.mjs +1 -1
  119. package/plugins/undoRedo/actions/columnSort.js +1 -1
  120. package/plugins/undoRedo/actions/columnSort.mjs +1 -1
  121. package/plugins/undoRedo/actions/createColumn.js +1 -1
  122. package/plugins/undoRedo/actions/createColumn.mjs +1 -1
  123. package/plugins/undoRedo/actions/createRow.js +1 -1
  124. package/plugins/undoRedo/actions/createRow.mjs +1 -1
  125. package/plugins/undoRedo/actions/dataChange.js +1 -1
  126. package/plugins/undoRedo/actions/dataChange.mjs +1 -1
  127. package/plugins/undoRedo/actions/filters.js +3 -3
  128. package/plugins/undoRedo/actions/filters.mjs +3 -3
  129. package/plugins/undoRedo/actions/mergeCells.js +4 -1
  130. package/plugins/undoRedo/actions/mergeCells.mjs +4 -1
  131. package/plugins/undoRedo/actions/removeColumn.js +4 -2
  132. package/plugins/undoRedo/actions/removeColumn.mjs +4 -2
  133. package/plugins/undoRedo/actions/removeRow.js +1 -1
  134. package/plugins/undoRedo/actions/removeRow.mjs +1 -1
  135. package/plugins/undoRedo/actions/rowMove.js +1 -1
  136. package/plugins/undoRedo/actions/rowMove.mjs +1 -1
  137. package/plugins/undoRedo/actions/unmergeCells.js +4 -1
  138. package/plugins/undoRedo/actions/unmergeCells.mjs +4 -1
  139. package/plugins/undoRedo/undoRedo.d.ts +48 -17
  140. package/renderers/checkboxRenderer/checkboxRenderer.js +1 -1
  141. package/renderers/checkboxRenderer/checkboxRenderer.mjs +2 -2
  142. package/renderers/numericRenderer/numericRenderer.js +10 -2
  143. package/renderers/numericRenderer/numericRenderer.mjs +10 -2
  144. package/renderers/textRenderer/textRenderer.js +3 -12
  145. package/renderers/textRenderer/textRenderer.mjs +4 -13
  146. package/shortcuts/utils.js +1 -0
  147. package/shortcuts/utils.mjs +1 -0
  148. package/styles/handsontable.css +83 -99
  149. package/styles/handsontable.min.css +3 -3
  150. package/styles/ht-theme-horizon.css +14 -2
  151. package/styles/ht-theme-horizon.min.css +3 -3
  152. package/styles/ht-theme-main.css +14 -2
  153. package/styles/ht-theme-main.min.css +3 -3
  154. package/tableView.js +9 -0
  155. package/tableView.mjs +9 -0
  156. package/translations/maps/linkedPhysicalIndexToValueMap.js +1 -0
  157. package/translations/maps/linkedPhysicalIndexToValueMap.mjs +1 -0
  158. package/translations/maps/utils/physicallyIndexed.js +1 -0
  159. package/translations/maps/utils/physicallyIndexed.mjs +1 -0
  160. package/utils/dataStructures/priorityMap.js +1 -0
  161. package/utils/dataStructures/priorityMap.mjs +1 -0
  162. package/plugins/multiColumnSorting/utils.js +0 -13
  163. 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;
@@ -562,12 +562,10 @@ class CopyPaste extends _base.BasePlugin {
562
562
  * @private
563
563
  */
564
564
  onCopy(event) {
565
- var _event$target, _this$hot$getSelected;
565
+ var _event$target;
566
566
  const focusedElement = this.hot.getFocusManager().getRefocusElement();
567
567
  const isHotInput = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.hasAttribute('data-hot-input');
568
- const selectedCell = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
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)) {
568
+ 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 && !(0, _element.isInternalElement)(event.target, this.hot.rootElement))) {
571
569
  return;
572
570
  }
573
571
  event.preventDefault();
@@ -597,12 +595,10 @@ class CopyPaste extends _base.BasePlugin {
597
595
  * @private
598
596
  */
599
597
  onCut(event) {
600
- var _event$target2, _this$hot$getSelected2;
598
+ var _event$target2;
601
599
  const focusedElement = this.hot.getFocusManager().getRefocusElement();
602
600
  const isHotInput = (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.hasAttribute('data-hot-input');
603
- const selectedCell = (_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.highlight;
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)) {
601
+ 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 && !(0, _element.isInternalElement)(event.target, this.hot.rootElement))) {
606
602
  return;
607
603
  }
608
604
  event.preventDefault();
@@ -631,12 +627,10 @@ class CopyPaste extends _base.BasePlugin {
631
627
  * @private
632
628
  */
633
629
  onPaste(event) {
634
- var _event$target3, _this$hot$getSelected3;
630
+ var _event$target3;
635
631
  const focusedElement = this.hot.getFocusManager().getRefocusElement();
636
632
  const isHotInput = (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.hasAttribute('data-hot-input');
637
- const selectedCell = (_this$hot$getSelected3 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected3 === void 0 ? void 0 : _this$hot$getSelected3.highlight;
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)) {
633
+ 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 && !(0, _element.isInternalElement)(event.target, this.hot.rootElement))) {
640
634
  return;
641
635
  }
642
636
  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, isInternalElement } 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";
@@ -558,12 +558,10 @@ export class CopyPaste extends BasePlugin {
558
558
  * @private
559
559
  */
560
560
  onCopy(event) {
561
- var _event$target, _this$hot$getSelected;
561
+ var _event$target;
562
562
  const focusedElement = this.hot.getFocusManager().getRefocusElement();
563
563
  const isHotInput = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.hasAttribute('data-hot-input');
564
- const selectedCell = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;
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)) {
564
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && !isInternalElement(event.target, this.hot.rootElement))) {
567
565
  return;
568
566
  }
569
567
  event.preventDefault();
@@ -593,12 +591,10 @@ export class CopyPaste extends BasePlugin {
593
591
  * @private
594
592
  */
595
593
  onCut(event) {
596
- var _event$target2, _this$hot$getSelected2;
594
+ var _event$target2;
597
595
  const focusedElement = this.hot.getFocusManager().getRefocusElement();
598
596
  const isHotInput = (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.hasAttribute('data-hot-input');
599
- const selectedCell = (_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.highlight;
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)) {
597
+ if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && !isInternalElement(event.target, this.hot.rootElement))) {
602
598
  return;
603
599
  }
604
600
  event.preventDefault();
@@ -627,12 +623,10 @@ export class CopyPaste extends BasePlugin {
627
623
  * @private
628
624
  */
629
625
  onPaste(event) {
630
- var _event$target3, _this$hot$getSelected3;
626
+ var _event$target3;
631
627
  const focusedElement = this.hot.getFocusManager().getRefocusElement();
632
628
  const isHotInput = (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.hasAttribute('data-hot-input');
633
- const selectedCell = (_this$hot$getSelected3 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected3 === void 0 ? void 0 : _this$hot$getSelected3.highlight;
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)) {
629
+ if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && !isInternalElement(event.target, this.hot.rootElement))) {
636
630
  return;
637
631
  }
638
632
  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) {