handsontable 0.0.0-next-abfe462-20231207 → 0.0.0-next-3d099da-20231208

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 (120) hide show
  1. package/3rdparty/walkontable/src/calculator/index.js +6 -11
  2. package/3rdparty/walkontable/src/calculator/index.mjs +3 -5
  3. package/3rdparty/walkontable/src/calculator/viewportColumns.js +122 -1
  4. package/3rdparty/walkontable/src/calculator/viewportColumns.mjs +124 -2
  5. package/3rdparty/walkontable/src/calculator/viewportRows.js +1 -1
  6. package/3rdparty/walkontable/src/calculator/viewportRows.mjs +3 -2
  7. package/3rdparty/walkontable/src/core/_base.js +12 -0
  8. package/3rdparty/walkontable/src/core/_base.mjs +12 -0
  9. package/3rdparty/walkontable/src/core/core.js +2 -0
  10. package/3rdparty/walkontable/src/core/core.mjs +2 -0
  11. package/3rdparty/walkontable/src/facade/core.js +9 -0
  12. package/3rdparty/walkontable/src/facade/core.mjs +9 -0
  13. package/3rdparty/walkontable/src/index.js +4 -3
  14. package/3rdparty/walkontable/src/index.mjs +2 -1
  15. package/3rdparty/walkontable/src/overlays.js +3 -0
  16. package/3rdparty/walkontable/src/overlays.mjs +4 -0
  17. package/3rdparty/walkontable/src/renderer/colGroup.js +0 -10
  18. package/3rdparty/walkontable/src/renderer/colGroup.mjs +0 -10
  19. package/3rdparty/walkontable/src/renderer/rows.js +3 -4
  20. package/3rdparty/walkontable/src/renderer/rows.mjs +3 -4
  21. package/3rdparty/walkontable/src/selection/manager.js +1 -0
  22. package/3rdparty/walkontable/src/selection/manager.mjs +1 -0
  23. package/3rdparty/walkontable/src/settings.js +0 -3
  24. package/3rdparty/walkontable/src/settings.mjs +0 -2
  25. package/3rdparty/walkontable/src/table.js +1 -0
  26. package/3rdparty/walkontable/src/table.mjs +1 -0
  27. package/3rdparty/walkontable/src/utils/column.js +12 -27
  28. package/3rdparty/walkontable/src/utils/column.mjs +12 -27
  29. package/3rdparty/walkontable/src/viewport.js +17 -22
  30. package/3rdparty/walkontable/src/viewport.mjs +18 -23
  31. package/base.js +2 -4
  32. package/base.mjs +2 -2
  33. package/core/focusCatcher/index.js +6 -44
  34. package/core/focusCatcher/index.mjs +6 -44
  35. package/core.js +11 -0
  36. package/core.mjs +11 -0
  37. package/dataMap/dataMap.js +0 -1
  38. package/dataMap/metaManager/metaSchema.js +2 -28
  39. package/dataMap/metaManager/metaSchema.mjs +2 -28
  40. package/dataMap/metaManager/mods/extendMetaProperties.js +0 -12
  41. package/dataMap/metaManager/mods/extendMetaProperties.mjs +0 -12
  42. package/dist/handsontable.css +2 -2
  43. package/dist/handsontable.full.css +2 -2
  44. package/dist/handsontable.full.js +3902 -2639
  45. package/dist/handsontable.full.min.css +2 -2
  46. package/dist/handsontable.full.min.js +70 -66
  47. package/dist/handsontable.js +3905 -2642
  48. package/dist/handsontable.min.css +2 -2
  49. package/dist/handsontable.min.js +39 -35
  50. package/editorManager.js +4 -3
  51. package/editorManager.mjs +4 -3
  52. package/editors/autocompleteEditor/autocompleteEditor.js +2 -0
  53. package/editors/autocompleteEditor/autocompleteEditor.mjs +2 -0
  54. package/editors/handsontableEditor/handsontableEditor.js +1 -0
  55. package/editors/handsontableEditor/handsontableEditor.mjs +1 -0
  56. package/editors/textEditor/textEditor.js +4 -0
  57. package/editors/textEditor/textEditor.mjs +4 -0
  58. package/helpers/mixed.js +1 -1
  59. package/helpers/mixed.mjs +1 -1
  60. package/package.json +1 -1
  61. package/pluginHooks.d.ts +29 -6
  62. package/pluginHooks.js +123 -65
  63. package/pluginHooks.mjs +122 -62
  64. package/plugins/copyPaste/clipboardData/clipboardData.js +588 -0
  65. package/plugins/copyPaste/clipboardData/clipboardData.mjs +584 -0
  66. package/plugins/copyPaste/clipboardData/copyClipboardData.js +69 -0
  67. package/plugins/copyPaste/clipboardData/copyClipboardData.mjs +65 -0
  68. package/plugins/copyPaste/clipboardData/index.js +9 -0
  69. package/plugins/copyPaste/clipboardData/index.mjs +4 -0
  70. package/plugins/copyPaste/clipboardData/pasteClipboardData.js +81 -0
  71. package/plugins/copyPaste/clipboardData/pasteClipboardData.mjs +77 -0
  72. package/plugins/copyPaste/copyPaste.js +51 -129
  73. package/plugins/copyPaste/copyPaste.mjs +54 -132
  74. package/plugins/copyPaste/copyableRanges.js +7 -43
  75. package/plugins/copyPaste/copyableRanges.mjs +7 -42
  76. package/plugins/copyPaste/pasteEvent.mjs +1 -1
  77. package/plugins/customBorders/customBorders.js +5 -0
  78. package/plugins/customBorders/customBorders.mjs +5 -0
  79. package/plugins/customBorders/utils.js +1 -0
  80. package/plugins/customBorders/utils.mjs +1 -0
  81. package/plugins/formulas/formulas.js +2 -0
  82. package/plugins/formulas/formulas.mjs +2 -0
  83. package/plugins/formulas/indexSyncer/axisSyncer.js +1 -0
  84. package/plugins/formulas/indexSyncer/axisSyncer.mjs +1 -0
  85. package/plugins/manualColumnResize/manualColumnResize.js +1 -0
  86. package/plugins/manualColumnResize/manualColumnResize.mjs +1 -0
  87. package/plugins/mergeCells/mergeCells.js +127 -1
  88. package/plugins/mergeCells/mergeCells.mjs +127 -1
  89. package/plugins/nestedHeaders/nestedHeaders.js +87 -41
  90. package/plugins/nestedHeaders/nestedHeaders.mjs +88 -42
  91. package/plugins/nestedHeaders/stateManager/headersTree.js +1 -0
  92. package/plugins/nestedHeaders/stateManager/headersTree.mjs +1 -0
  93. package/plugins/undoRedo/undoRedo.js +2 -0
  94. package/plugins/undoRedo/undoRedo.mjs +2 -0
  95. package/renderers/autocompleteRenderer/autocompleteRenderer.js +1 -0
  96. package/renderers/autocompleteRenderer/autocompleteRenderer.mjs +1 -0
  97. package/renderers/checkboxRenderer/checkboxRenderer.js +2 -0
  98. package/renderers/checkboxRenderer/checkboxRenderer.mjs +2 -0
  99. package/selection/highlight/highlight.js +1 -0
  100. package/selection/highlight/highlight.mjs +1 -0
  101. package/selection/index.js +3 -1
  102. package/selection/index.mjs +2 -2
  103. package/selection/utils.js +34 -0
  104. package/selection/utils.mjs +33 -0
  105. package/settings.d.ts +0 -1
  106. package/tableView.js +2 -1
  107. package/tableView.mjs +2 -1
  108. package/translations/indexMapper.js +1 -2
  109. package/utils/parseTable.js +538 -84
  110. package/utils/parseTable.mjs +534 -83
  111. package/validators/timeValidator/timeValidator.js +1 -0
  112. package/validators/timeValidator/timeValidator.mjs +1 -0
  113. package/3rdparty/walkontable/src/calculator/renderAllColumns.js +0 -50
  114. package/3rdparty/walkontable/src/calculator/renderAllColumns.mjs +0 -46
  115. package/3rdparty/walkontable/src/calculator/renderAllRows.js +0 -50
  116. package/3rdparty/walkontable/src/calculator/renderAllRows.mjs +0 -46
  117. package/3rdparty/walkontable/src/utils/columnStretching.js +0 -219
  118. package/3rdparty/walkontable/src/utils/columnStretching.mjs +0 -215
  119. package/plugins/copyPaste/clipboardData.js +0 -18
  120. package/plugins/copyPaste/clipboardData.mjs +0 -14
@@ -17,6 +17,7 @@ var _number = require("../../helpers/number");
17
17
  var _utils = require("./utils");
18
18
  var _element = require("../../helpers/dom/element");
19
19
  var _browser = require("../../helpers/browser");
20
+ var _mixed = require("../../helpers/mixed");
20
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
22
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
22
23
  function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
@@ -98,9 +99,26 @@ var _onBeforeDrawAreaBorders = /*#__PURE__*/new WeakSet();
98
99
  var _onAfterModifyTransformStart = /*#__PURE__*/new WeakSet();
99
100
  var _onAfterDrawSelection = /*#__PURE__*/new WeakSet();
100
101
  var _onBeforeRemoveCellClassNames = /*#__PURE__*/new WeakSet();
102
+ var _onBeforePaste = /*#__PURE__*/new WeakSet();
101
103
  class MergeCells extends _base.BasePlugin {
102
104
  constructor() {
103
105
  super(...arguments);
106
+ /**
107
+ * `beforePaste` hook callback. Used for manipulating with area of paste (by changing selection) and unmerging cells.
108
+ *
109
+ * @private
110
+ * @param {object} clipboardData Information about copy action which is going to happen.
111
+ * @param {Function} clipboardData.removeRow Remove row from the copied dataset.
112
+ * @param {Function} clipboardData.removeColumn Remove column from the copied dataset.
113
+ * @param {Function} clipboardData.insertAtRow Insert values at row index.
114
+ * @param {Function} clipboardData.insertAtColumn Insert values at column index.
115
+ * @param {Function} clipboardData.setCellAt Change headers or cells in the copied dataset.
116
+ * @param {Function} clipboardData.getCellAt Get headers or cells from the copied dataset.
117
+ * @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
118
+ * @param {Function} clipboardData.getMetaInfo Gets meta information for the copied data.
119
+ * @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
120
+ */
121
+ _classPrivateMethodInitSpec(this, _onBeforePaste);
104
122
  /**
105
123
  * `beforeRemoveCellClassNames` hook callback. Used to remove additional class name from all cells in the table.
106
124
  *
@@ -464,6 +482,12 @@ class MergeCells extends _base.BasePlugin {
464
482
  return false;
465
483
  }
466
484
  });
485
+ this.addHook('beforePaste', function () {
486
+ for (var _len24 = arguments.length, args = new Array(_len24), _key24 = 0; _key24 < _len24; _key24++) {
487
+ args[_key24] = arguments[_key24];
488
+ }
489
+ return _classPrivateMethodGet(_this, _onBeforePaste, _onBeforePaste2).call(_this, ...args);
490
+ });
467
491
  this.registerShortcuts();
468
492
  super.enablePlugin();
469
493
  }
@@ -749,13 +773,15 @@ class MergeCells extends _base.BasePlugin {
749
773
  * @private
750
774
  * @param {CellRange} cellRange Selection cell range.
751
775
  * @param {boolean} [auto=false] `true` if called automatically by the plugin.
776
+ * @param {boolean} [unmergePartials=false] If set to `true`, all the merged cells overlapping the range will be unmerged.
752
777
  *
753
778
  * @fires Hooks#beforeUnmergeCells
754
779
  * @fires Hooks#afterUnmergeCells
755
780
  */
756
781
  unmergeRange(cellRange) {
757
782
  let auto = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
758
- const mergedCells = this.mergedCellsCollection.getWithinRange(cellRange);
783
+ let unmergePartials = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
784
+ const mergedCells = this.mergedCellsCollection.getWithinRange(cellRange, unmergePartials);
759
785
  if (!mergedCells) {
760
786
  return;
761
787
  }
@@ -910,6 +936,7 @@ class MergeCells extends _base.BasePlugin {
910
936
  }
911
937
  }
912
938
  }
939
+
913
940
  /**
914
941
  * Modify viewport start when needed. We extend viewport when merged cells aren't fully visible.
915
942
  *
@@ -1004,6 +1031,67 @@ class MergeCells extends _base.BasePlugin {
1004
1031
  const renderableColumn = parentColumn >= 0 ? columnMapper.getRenderableFromVisualIndex(firstNonHiddenColumn) : parentColumn;
1005
1032
  return [renderableRow, renderableColumn];
1006
1033
  }
1034
+ /**
1035
+ * Creates cell range.
1036
+ *
1037
+ * @private
1038
+ * @param {number} startRow Visual start row index for the range.
1039
+ * @param {number} startColumn Visual start column index for the range.
1040
+ * @param {number} numberOfRows Number of rows within the range.
1041
+ * @param {number} numberOfColumns Number of columns within the range.
1042
+ * @returns {CellRange}
1043
+ */
1044
+ getCellRange(startRow, startColumn, numberOfRows, numberOfColumns) {
1045
+ const rangeStart = this.hot._createCellCoords(startRow, startColumn);
1046
+ const rangeEnd = this.hot._createCellCoords(startRow + numberOfRows - 1, startColumn + numberOfColumns - 1);
1047
+ return this.hot._createCellRange(rangeStart, rangeStart, rangeEnd);
1048
+ }
1049
+
1050
+ /**
1051
+ * Adjusting selection to select complete area of previously merged cells.
1052
+ *
1053
+ * @private
1054
+ * @param {Array|boolean} listOfUnmergedCells Array of found merged cells of `false` if none were found.
1055
+ * @param {CellRange} unmergedRange Range for unmerged cells.
1056
+ */
1057
+ adjustSelectionAfterPasting(listOfUnmergedCells, unmergedRange) {
1058
+ if (listOfUnmergedCells === false) {
1059
+ return;
1060
+ }
1061
+ listOfUnmergedCells.forEach(mergedCell => {
1062
+ const {
1063
+ row,
1064
+ col,
1065
+ rowspan,
1066
+ colspan
1067
+ } = mergedCell;
1068
+ const mergeRange = this.getCellRange(row, col, rowspan, colspan);
1069
+ unmergedRange.expandByRange(mergeRange);
1070
+ });
1071
+ this.hot.addHookOnce('afterPaste', () => {
1072
+ this.hot.selectCell(unmergedRange.from.row, unmergedRange.from.col, unmergedRange.to.row, unmergedRange.to.col);
1073
+ });
1074
+ }
1075
+
1076
+ /**
1077
+ * Checks if unmerge should be performed.
1078
+ *
1079
+ * @private
1080
+ * @param {Array<object>} mergedCells List of merged cells.
1081
+ * @param {number} pastedRows Number of pasted data rows.
1082
+ * @param {number} pastedColumns Number of pasted data columns.
1083
+ * @returns {boolean}
1084
+ */
1085
+ shouldUnmerge(mergedCells, pastedRows, pastedColumns) {
1086
+ const isCopiedWithMergedCell = (0, _mixed.isDefined)(mergedCells);
1087
+ const copiedOnlyMergedCell = isCopiedWithMergedCell && mergedCells.length === 1 && mergedCells[0].rowspan === pastedRows && mergedCells[0].colspan === pastedColumns;
1088
+ const selectedRangeLast = this.hot.getSelectedRangeLast();
1089
+ const pastingToMergedCell = this.mergedCellsCollection.getByRange(selectedRangeLast) !== false;
1090
+ if (pastedRows === 1 && pastedColumns === 1 && pastingToMergedCell === true) {
1091
+ return false;
1092
+ }
1093
+ return copiedOnlyMergedCell === false || pastingToMergedCell === false;
1094
+ }
1007
1095
  }
1008
1096
  exports.MergeCells = MergeCells;
1009
1097
  function _onAfterInit2() {
@@ -1042,6 +1130,7 @@ function _onModifyTransformStart2(delta) {
1042
1130
  if (!mergeRange.includes(_classPrivateFieldGet(this, _lastDesiredCoords))) {
1043
1131
  _classPrivateFieldSet(this, _lastDesiredCoords, this.hot._createCellCoords(null, null)); // reset outdated version of lastDesiredCoords
1044
1132
  }
1133
+
1045
1134
  newDelta.row = _classPrivateFieldGet(this, _lastDesiredCoords).row ? _classPrivateFieldGet(this, _lastDesiredCoords).row - currentPosition.row : newDelta.row;
1046
1135
  newDelta.col = _classPrivateFieldGet(this, _lastDesiredCoords).col ? _classPrivateFieldGet(this, _lastDesiredCoords).col - currentPosition.col : newDelta.col;
1047
1136
  if (delta.row > 0) {
@@ -1290,4 +1379,41 @@ function _onAfterDrawSelection2(currentRow, currentColumn, cornersOfSelection, l
1290
1379
  }
1291
1380
  function _onBeforeRemoveCellClassNames2() {
1292
1381
  return this.selectionCalculations.getSelectedMergedCellClassNameToRemove();
1382
+ }
1383
+ function _onBeforePaste2(clipboardData) {
1384
+ const selectedRangeLast = this.hot.getSelectedRangeLast();
1385
+ const data = clipboardData.getData();
1386
+ const pastedRows = data.length;
1387
+ const pastedColumns = data[0].length;
1388
+ const {
1389
+ row: selectionFromRow,
1390
+ col: selectionFromColumn
1391
+ } = selectedRangeLast.from;
1392
+ const selectedRows = selectedRangeLast.getHeight();
1393
+ const selectedColumns = selectedRangeLast.getWidth();
1394
+ if (this.shouldUnmerge(clipboardData.getMetaInfo().mergeCells, pastedRows, pastedColumns) === false) {
1395
+ return;
1396
+ }
1397
+ const pasteRange = this.getCellRange(selectionFromRow, selectionFromColumn, pastedRows, pastedColumns);
1398
+ const populationRange = this.getCellRange(selectionFromRow, selectionFromColumn, Math.max(pastedRows, selectedRows), Math.max(pastedColumns, selectedColumns));
1399
+ let rangeToUnmerge = pasteRange;
1400
+ const mergedCellsWithinPopulation = this.mergedCellsCollection.getWithinRange(populationRange, true);
1401
+
1402
+ // Nothing to unmerge.
1403
+ if (mergedCellsWithinPopulation.length === 0) {
1404
+ return;
1405
+ }
1406
+ if (mergedCellsWithinPopulation.length === 1) {
1407
+ rangeToUnmerge = populationRange;
1408
+ }
1409
+
1410
+ // Checking merged cells on unmerge range right before performing the unmerge.
1411
+ const listOfUnmergedCells = this.mergedCellsCollection.getWithinRange(rangeToUnmerge, true);
1412
+ this.unmergeRange(rangeToUnmerge, false, true);
1413
+
1414
+ // Changing selection (place where the data is populated) only for greater range (at least two merged cells).
1415
+ if (rangeToUnmerge === pasteRange) {
1416
+ this.hot.selectCell(selectionFromRow, selectionFromColumn, pasteRange.endRow, pasteRange.endCol);
1417
+ }
1418
+ this.adjustSelectionAfterPasting(listOfUnmergedCells, rangeToUnmerge);
1293
1419
  }
@@ -26,6 +26,7 @@ import { rangeEach } from "../../helpers/number.mjs";
26
26
  import { applySpanProperties } from "./utils.mjs";
27
27
  import { getStyle } from "../../helpers/dom/element.mjs";
28
28
  import { isChrome } from "../../helpers/browser.mjs";
29
+ import { isDefined } from "../../helpers/mixed.mjs";
29
30
  Hooks.getSingleton().register('beforeMergeCells');
30
31
  Hooks.getSingleton().register('afterMergeCells');
31
32
  Hooks.getSingleton().register('beforeUnmergeCells');
@@ -94,9 +95,26 @@ var _onBeforeDrawAreaBorders = /*#__PURE__*/new WeakSet();
94
95
  var _onAfterModifyTransformStart = /*#__PURE__*/new WeakSet();
95
96
  var _onAfterDrawSelection = /*#__PURE__*/new WeakSet();
96
97
  var _onBeforeRemoveCellClassNames = /*#__PURE__*/new WeakSet();
98
+ var _onBeforePaste = /*#__PURE__*/new WeakSet();
97
99
  export class MergeCells extends BasePlugin {
98
100
  constructor() {
99
101
  super(...arguments);
102
+ /**
103
+ * `beforePaste` hook callback. Used for manipulating with area of paste (by changing selection) and unmerging cells.
104
+ *
105
+ * @private
106
+ * @param {object} clipboardData Information about copy action which is going to happen.
107
+ * @param {Function} clipboardData.removeRow Remove row from the copied dataset.
108
+ * @param {Function} clipboardData.removeColumn Remove column from the copied dataset.
109
+ * @param {Function} clipboardData.insertAtRow Insert values at row index.
110
+ * @param {Function} clipboardData.insertAtColumn Insert values at column index.
111
+ * @param {Function} clipboardData.setCellAt Change headers or cells in the copied dataset.
112
+ * @param {Function} clipboardData.getCellAt Get headers or cells from the copied dataset.
113
+ * @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
114
+ * @param {Function} clipboardData.getMetaInfo Gets meta information for the copied data.
115
+ * @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
116
+ */
117
+ _classPrivateMethodInitSpec(this, _onBeforePaste);
100
118
  /**
101
119
  * `beforeRemoveCellClassNames` hook callback. Used to remove additional class name from all cells in the table.
102
120
  *
@@ -460,6 +478,12 @@ export class MergeCells extends BasePlugin {
460
478
  return false;
461
479
  }
462
480
  });
481
+ this.addHook('beforePaste', function () {
482
+ for (var _len24 = arguments.length, args = new Array(_len24), _key24 = 0; _key24 < _len24; _key24++) {
483
+ args[_key24] = arguments[_key24];
484
+ }
485
+ return _classPrivateMethodGet(_this, _onBeforePaste, _onBeforePaste2).call(_this, ...args);
486
+ });
463
487
  this.registerShortcuts();
464
488
  super.enablePlugin();
465
489
  }
@@ -745,13 +769,15 @@ export class MergeCells extends BasePlugin {
745
769
  * @private
746
770
  * @param {CellRange} cellRange Selection cell range.
747
771
  * @param {boolean} [auto=false] `true` if called automatically by the plugin.
772
+ * @param {boolean} [unmergePartials=false] If set to `true`, all the merged cells overlapping the range will be unmerged.
748
773
  *
749
774
  * @fires Hooks#beforeUnmergeCells
750
775
  * @fires Hooks#afterUnmergeCells
751
776
  */
752
777
  unmergeRange(cellRange) {
753
778
  let auto = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
754
- const mergedCells = this.mergedCellsCollection.getWithinRange(cellRange);
779
+ let unmergePartials = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
780
+ const mergedCells = this.mergedCellsCollection.getWithinRange(cellRange, unmergePartials);
755
781
  if (!mergedCells) {
756
782
  return;
757
783
  }
@@ -906,6 +932,7 @@ export class MergeCells extends BasePlugin {
906
932
  }
907
933
  }
908
934
  }
935
+
909
936
  /**
910
937
  * Modify viewport start when needed. We extend viewport when merged cells aren't fully visible.
911
938
  *
@@ -1000,6 +1027,67 @@ export class MergeCells extends BasePlugin {
1000
1027
  const renderableColumn = parentColumn >= 0 ? columnMapper.getRenderableFromVisualIndex(firstNonHiddenColumn) : parentColumn;
1001
1028
  return [renderableRow, renderableColumn];
1002
1029
  }
1030
+ /**
1031
+ * Creates cell range.
1032
+ *
1033
+ * @private
1034
+ * @param {number} startRow Visual start row index for the range.
1035
+ * @param {number} startColumn Visual start column index for the range.
1036
+ * @param {number} numberOfRows Number of rows within the range.
1037
+ * @param {number} numberOfColumns Number of columns within the range.
1038
+ * @returns {CellRange}
1039
+ */
1040
+ getCellRange(startRow, startColumn, numberOfRows, numberOfColumns) {
1041
+ const rangeStart = this.hot._createCellCoords(startRow, startColumn);
1042
+ const rangeEnd = this.hot._createCellCoords(startRow + numberOfRows - 1, startColumn + numberOfColumns - 1);
1043
+ return this.hot._createCellRange(rangeStart, rangeStart, rangeEnd);
1044
+ }
1045
+
1046
+ /**
1047
+ * Adjusting selection to select complete area of previously merged cells.
1048
+ *
1049
+ * @private
1050
+ * @param {Array|boolean} listOfUnmergedCells Array of found merged cells of `false` if none were found.
1051
+ * @param {CellRange} unmergedRange Range for unmerged cells.
1052
+ */
1053
+ adjustSelectionAfterPasting(listOfUnmergedCells, unmergedRange) {
1054
+ if (listOfUnmergedCells === false) {
1055
+ return;
1056
+ }
1057
+ listOfUnmergedCells.forEach(mergedCell => {
1058
+ const {
1059
+ row,
1060
+ col,
1061
+ rowspan,
1062
+ colspan
1063
+ } = mergedCell;
1064
+ const mergeRange = this.getCellRange(row, col, rowspan, colspan);
1065
+ unmergedRange.expandByRange(mergeRange);
1066
+ });
1067
+ this.hot.addHookOnce('afterPaste', () => {
1068
+ this.hot.selectCell(unmergedRange.from.row, unmergedRange.from.col, unmergedRange.to.row, unmergedRange.to.col);
1069
+ });
1070
+ }
1071
+
1072
+ /**
1073
+ * Checks if unmerge should be performed.
1074
+ *
1075
+ * @private
1076
+ * @param {Array<object>} mergedCells List of merged cells.
1077
+ * @param {number} pastedRows Number of pasted data rows.
1078
+ * @param {number} pastedColumns Number of pasted data columns.
1079
+ * @returns {boolean}
1080
+ */
1081
+ shouldUnmerge(mergedCells, pastedRows, pastedColumns) {
1082
+ const isCopiedWithMergedCell = isDefined(mergedCells);
1083
+ const copiedOnlyMergedCell = isCopiedWithMergedCell && mergedCells.length === 1 && mergedCells[0].rowspan === pastedRows && mergedCells[0].colspan === pastedColumns;
1084
+ const selectedRangeLast = this.hot.getSelectedRangeLast();
1085
+ const pastingToMergedCell = this.mergedCellsCollection.getByRange(selectedRangeLast) !== false;
1086
+ if (pastedRows === 1 && pastedColumns === 1 && pastingToMergedCell === true) {
1087
+ return false;
1088
+ }
1089
+ return copiedOnlyMergedCell === false || pastingToMergedCell === false;
1090
+ }
1003
1091
  }
1004
1092
  function _onAfterInit2() {
1005
1093
  this.generateFromSettings(this.hot.getSettings()[PLUGIN_KEY]);
@@ -1037,6 +1125,7 @@ function _onModifyTransformStart2(delta) {
1037
1125
  if (!mergeRange.includes(_classPrivateFieldGet(this, _lastDesiredCoords))) {
1038
1126
  _classPrivateFieldSet(this, _lastDesiredCoords, this.hot._createCellCoords(null, null)); // reset outdated version of lastDesiredCoords
1039
1127
  }
1128
+
1040
1129
  newDelta.row = _classPrivateFieldGet(this, _lastDesiredCoords).row ? _classPrivateFieldGet(this, _lastDesiredCoords).row - currentPosition.row : newDelta.row;
1041
1130
  newDelta.col = _classPrivateFieldGet(this, _lastDesiredCoords).col ? _classPrivateFieldGet(this, _lastDesiredCoords).col - currentPosition.col : newDelta.col;
1042
1131
  if (delta.row > 0) {
@@ -1285,4 +1374,41 @@ function _onAfterDrawSelection2(currentRow, currentColumn, cornersOfSelection, l
1285
1374
  }
1286
1375
  function _onBeforeRemoveCellClassNames2() {
1287
1376
  return this.selectionCalculations.getSelectedMergedCellClassNameToRemove();
1377
+ }
1378
+ function _onBeforePaste2(clipboardData) {
1379
+ const selectedRangeLast = this.hot.getSelectedRangeLast();
1380
+ const data = clipboardData.getData();
1381
+ const pastedRows = data.length;
1382
+ const pastedColumns = data[0].length;
1383
+ const {
1384
+ row: selectionFromRow,
1385
+ col: selectionFromColumn
1386
+ } = selectedRangeLast.from;
1387
+ const selectedRows = selectedRangeLast.getHeight();
1388
+ const selectedColumns = selectedRangeLast.getWidth();
1389
+ if (this.shouldUnmerge(clipboardData.getMetaInfo().mergeCells, pastedRows, pastedColumns) === false) {
1390
+ return;
1391
+ }
1392
+ const pasteRange = this.getCellRange(selectionFromRow, selectionFromColumn, pastedRows, pastedColumns);
1393
+ const populationRange = this.getCellRange(selectionFromRow, selectionFromColumn, Math.max(pastedRows, selectedRows), Math.max(pastedColumns, selectedColumns));
1394
+ let rangeToUnmerge = pasteRange;
1395
+ const mergedCellsWithinPopulation = this.mergedCellsCollection.getWithinRange(populationRange, true);
1396
+
1397
+ // Nothing to unmerge.
1398
+ if (mergedCellsWithinPopulation.length === 0) {
1399
+ return;
1400
+ }
1401
+ if (mergedCellsWithinPopulation.length === 1) {
1402
+ rangeToUnmerge = populationRange;
1403
+ }
1404
+
1405
+ // Checking merged cells on unmerge range right before performing the unmerge.
1406
+ const listOfUnmergedCells = this.mergedCellsCollection.getWithinRange(rangeToUnmerge, true);
1407
+ this.unmergeRange(rangeToUnmerge, false, true);
1408
+
1409
+ // Changing selection (place where the data is populated) only for greater range (at least two merged cells).
1410
+ if (rangeToUnmerge === pasteRange) {
1411
+ this.hot.selectCell(selectionFromRow, selectionFromColumn, pasteRange.endRow, pasteRange.endCol);
1412
+ }
1413
+ this.adjustSelectionAfterPasting(listOfUnmergedCells, rangeToUnmerge);
1288
1414
  }
@@ -12,6 +12,7 @@ var _selection = require("../../selection");
12
12
  var _base = require("../base");
13
13
  var _stateManager2 = _interopRequireDefault(require("./stateManager"));
14
14
  var _ghostTable = _interopRequireDefault(require("./utils/ghostTable"));
15
+ var _array = require("../../helpers/array");
15
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
17
18
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -101,6 +102,7 @@ class NestedHeaders extends _base.BasePlugin {
101
102
  /**
102
103
  * Updates the plugin state after new dataset load.
103
104
  *
105
+ * @private
104
106
  * @param {Array[]} sourceData Array of arrays or array of objects containing data.
105
107
  * @param {boolean} initialLoad Flag that determines whether the data has been loaded
106
108
  * during the initialization.
@@ -108,11 +110,14 @@ class NestedHeaders extends _base.BasePlugin {
108
110
  _classPrivateMethodInitSpec(this, _onAfterLoadData);
109
111
  /**
110
112
  * Updates the plugin state after HoT initialization.
113
+ *
114
+ * @private
111
115
  */
112
116
  _classPrivateMethodInitSpec(this, _onInit);
113
117
  /**
114
118
  * `modifyFocusedElement` hook callback.
115
119
  *
120
+ * @private
116
121
  * @param {number} row Row index.
117
122
  * @param {number} column Column index.
118
123
  * @returns {HTMLTableCellElement} The `TH` element to be focused.
@@ -122,6 +127,7 @@ class NestedHeaders extends _base.BasePlugin {
122
127
  * Listens the `modifyColumnHeaderValue` hook that overwrites the column headers values based on
123
128
  * the internal state and settings of the plugin.
124
129
  *
130
+ * @private
125
131
  * @param {string} value The column header value.
126
132
  * @param {number} visualColumnIndex The visual column index.
127
133
  * @param {number} headerLevel The index of header level. The header level accepts positive (0 to N)
@@ -134,6 +140,7 @@ class NestedHeaders extends _base.BasePlugin {
134
140
  /**
135
141
  * `modifyColWidth` hook callback - returns width from cache, when is greater than incoming from hook.
136
142
  *
143
+ * @private
137
144
  * @param {number} width Width from hook.
138
145
  * @param {number} column Visual index of an column.
139
146
  * @returns {number}
@@ -142,12 +149,14 @@ class NestedHeaders extends _base.BasePlugin {
142
149
  /**
143
150
  * Make the renderer render the first nested column in its entirety.
144
151
  *
152
+ * @private
145
153
  * @param {object} calc Viewport column calculator.
146
154
  */
147
155
  _classPrivateMethodInitSpec(this, _onAfterViewportColumnCalculatorOverride);
148
156
  /**
149
157
  * `afterGetColumnHeader` hook callback - prepares the header structure.
150
158
  *
159
+ * @private
151
160
  * @param {Array} renderersArray Array of renderers.
152
161
  */
153
162
  _classPrivateMethodInitSpec(this, _onAfterGetColumnHeaderRenderers);
@@ -155,6 +164,7 @@ class NestedHeaders extends _base.BasePlugin {
155
164
  * The hook observes the column selection from the Selection API and modifies the column range to
156
165
  * ensure that the whole nested column will be covered.
157
166
  *
167
+ * @private
158
168
  * @param {CellCoords} from The coords object where the selection starts.
159
169
  * @param {CellCoords} to The coords object where the selection ends.
160
170
  */
@@ -162,21 +172,27 @@ class NestedHeaders extends _base.BasePlugin {
162
172
  /**
163
173
  * `modifyTransformStart` hook is called every time the keyboard navigation is used.
164
174
  *
175
+ * @private
165
176
  * @param {object} delta The transformation delta.
166
177
  */
167
178
  _classPrivateMethodInitSpec(this, _onModifyTransformStart);
168
179
  /**
169
180
  * The hook checks and ensures that the focus position that depends on the selected columns
170
181
  * range is always positioned within the range.
182
+ *
183
+ * @private
171
184
  */
172
185
  _classPrivateMethodInitSpec(this, _onBeforeSelectionHighlightSet);
173
186
  /**
174
187
  * Switches internal flag about selection progress to `false`.
188
+ *
189
+ * @private
175
190
  */
176
191
  _classPrivateMethodInitSpec(this, _onBeforeOnCellMouseUp);
177
192
  /**
178
193
  * Makes the header-selection properly select the nested headers.
179
194
  *
195
+ * @private
180
196
  * @param {MouseEvent} event Mouse event.
181
197
  * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
182
198
  * @param {HTMLElement} TD The cell element.
@@ -187,6 +203,7 @@ class NestedHeaders extends _base.BasePlugin {
187
203
  /**
188
204
  * Allows to control how the column selection based on the coordinates and the nested headers is made.
189
205
  *
206
+ * @private
190
207
  * @param {MouseEvent} event Mouse event.
191
208
  * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
192
209
  */
@@ -194,6 +211,7 @@ class NestedHeaders extends _base.BasePlugin {
194
211
  /**
195
212
  * Allows blocking the column selection that is controlled by the core Selection module.
196
213
  *
214
+ * @private
197
215
  * @param {MouseEvent} event Mouse event.
198
216
  * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
199
217
  * @param {CellCoords} TD The table cell or header element.
@@ -207,16 +225,23 @@ class NestedHeaders extends _base.BasePlugin {
207
225
  * of the column.
208
226
  *
209
227
  * @private
210
- * @param {Array[]} data An array of arrays which contains data to copied.
211
- * @param {object[]} copyableRanges An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
212
- * which will copied.
213
- * @param {{ columnHeadersCount: number }} copiedHeadersCount An object with keys that holds information with
214
- * the number of copied headers.
228
+ * @param {object} clipboardData Information about already performed copy action.
229
+ * @param {Function} clipboardData.removeRow Remove row from the copied/pasted dataset.
230
+ * @param {Function} clipboardData.removeColumn Remove column from the copied/pasted dataset.
231
+ * @param {Function} clipboardData.insertAtRow Insert values at row index.
232
+ * @param {Function} clipboardData.insertAtColumn Insert values at column index.
233
+ * @param {Function} clipboardData.setCellAt Change headers or cells in the copied/pasted dataset.
234
+ * @param {Function} clipboardData.getCellAt Get headers or cells from the copied/pasted dataset.
235
+ * @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
236
+ * @param {Function} clipboardData.getMetaInfo Gets grid settings for copied data.
237
+ * @param {Function} clipboardData.setMetaInfo Sets grid settings for copied data.
238
+ * @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
215
239
  */
216
240
  _classPrivateMethodInitSpec(this, _onBeforeCopy);
217
241
  /**
218
242
  * Allows to control which header DOM element will be used to highlight.
219
243
  *
244
+ * @private
220
245
  * @param {number} visualColumn A visual column index of the highlighted row header.
221
246
  * @param {number} headerLevel A row header level that is currently highlighted.
222
247
  * @param {object} highlightMeta An object with meta data that describes the highlight state.
@@ -228,6 +253,7 @@ class NestedHeaders extends _base.BasePlugin {
228
253
  * is scrolled to the correct column for the nested header the most left and the most right visual column
229
254
  * indexes are used.
230
255
  *
256
+ * @private
231
257
  * @param {number} visualColumn A visual column index to which the viewport will be scrolled.
232
258
  * @returns {number}
233
259
  */
@@ -235,6 +261,8 @@ class NestedHeaders extends _base.BasePlugin {
235
261
  /**
236
262
  * Updates the selection focus highlight position to point to the nested header root element (TH)
237
263
  * even when the logical coordinates point in-between the header.
264
+ *
265
+ * @private
238
266
  */
239
267
  _classPrivateMethodInitSpec(this, _updateFocusHighlightPosition);
240
268
  /**
@@ -726,42 +754,60 @@ function _onBeforeHighlightingColumnHeader2(visualColumn, headerLevel, highlight
726
754
  }
727
755
  return visualColumn;
728
756
  }
729
- function _onBeforeCopy2(data, copyableRanges, _ref2) {
730
- let {
731
- columnHeadersCount
732
- } = _ref2;
733
- if (columnHeadersCount === 0) {
734
- return;
735
- }
736
- for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex++) {
737
- const {
738
- startRow,
739
- startCol,
740
- endRow,
741
- endCol
742
- } = copyableRanges[rangeIndex];
743
- const rowsCount = endRow - startRow + 1;
744
- const columnsCount = startCol - endCol + 1;
745
-
746
- // do not process dataset ranges and column headers where only one column is copied
747
- if (startRow >= 0 || columnsCount === 1) {
748
- break;
749
- }
750
- for (let column = startCol; column <= endCol; column++) {
751
- for (let row = startRow; row <= endRow; row++) {
752
- var _classPrivateFieldGet4;
753
- const zeroBasedColumnHeaderLevel = rowsCount + row;
754
- const zeroBasedColumnIndex = column - startCol;
755
- if (zeroBasedColumnIndex === 0) {
756
- continue; // eslint-disable-line no-continue
757
- }
758
- const isRoot = (_classPrivateFieldGet4 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4.isRoot;
759
- if (isRoot === false) {
760
- data[zeroBasedColumnHeaderLevel][zeroBasedColumnIndex] = '';
757
+ function _onBeforeCopy2(clipboardData) {
758
+ const {
759
+ rows,
760
+ columns
761
+ } = (0, _selection.transformRangeLikeToIndexes)(clipboardData.getRanges());
762
+ const headers = rows.filter(row => row < 0);
763
+ const nestedHeaders = [];
764
+ headers.forEach(header => {
765
+ const headersForLevel = [];
766
+ (0, _array.arrayEach)(columns, (column, index) => {
767
+ const headerSettings = this.getHeaderSettings(header, column);
768
+ if (headerSettings === null) {
769
+ headersForLevel.push(this.hot.getColHeader(column, header));
770
+ return;
771
+ }
772
+ const {
773
+ isPlaceholder
774
+ } = headerSettings;
775
+ const columnsToEnd = columns.slice(index).length;
776
+ const headerTreeNodeData = this.getStateManager().getHeaderTreeNodeData(header, column);
777
+ if (index === 0 && isPlaceholder === true) {
778
+ const {
779
+ label,
780
+ origColspan: colspan,
781
+ columnIndex
782
+ } = headerTreeNodeData;
783
+ const columnFromStart = column - columnIndex;
784
+ const reducedColspan = Math.min(colspan - columnFromStart, columnsToEnd);
785
+ if (reducedColspan > 1) {
786
+ headersForLevel.push({
787
+ label,
788
+ colspan: reducedColspan
789
+ });
790
+ } else {
791
+ headersForLevel.push(label);
761
792
  }
793
+ } else if (isPlaceholder === false) {
794
+ const {
795
+ label,
796
+ origColspan: colspan,
797
+ columnIndex
798
+ } = headerTreeNodeData;
799
+ const columnFromStart = column - columnIndex;
800
+ const reducedColspan = Math.min(colspan - columnFromStart, columnsToEnd);
801
+ headersForLevel.push(reducedColspan > 1 ? {
802
+ label,
803
+ colspan: reducedColspan
804
+ } : label);
762
805
  }
763
- }
764
- }
806
+ });
807
+ nestedHeaders.push(headersForLevel);
808
+ });
809
+ clipboardData.setMetaInfo('colHeaders', null);
810
+ clipboardData.setMetaInfo('nestedHeaders', nestedHeaders);
765
811
  }
766
812
  function _onBeforeOnCellMouseDown2(event, coords, TD, controller) {
767
813
  const headerNodeData = this._getHeaderTreeNodeDataByCoords(coords);
@@ -964,10 +1010,10 @@ function _onModifyColWidth2(width, column) {
964
1010
  return width > cachedWidth ? width : cachedWidth;
965
1011
  }
966
1012
  function _onModifyColumnHeaderValue2(value, visualColumnIndex, headerLevel) {
967
- var _classPrivateFieldGet5;
1013
+ var _classPrivateFieldGet4;
968
1014
  const {
969
1015
  label
970
- } = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet5 !== void 0 ? _classPrivateFieldGet5 : {
1016
+ } = (_classPrivateFieldGet4 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet4 !== void 0 ? _classPrivateFieldGet4 : {
971
1017
  label: ''
972
1018
  };
973
1019
  return label;