handsontable 14.0.0-next-c22ab6f-20231030 → 14.0.0-next-f88c253-20231106

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/base.js +2 -2
  2. package/base.mjs +2 -2
  3. package/dist/handsontable.css +8 -2
  4. package/dist/handsontable.full.css +8 -2
  5. package/dist/handsontable.full.js +2084 -3359
  6. package/dist/handsontable.full.min.css +3 -3
  7. package/dist/handsontable.full.min.js +59 -66
  8. package/dist/handsontable.js +2086 -3361
  9. package/dist/handsontable.min.css +3 -3
  10. package/dist/handsontable.min.js +16 -23
  11. package/helpers/mixed.js +2 -2
  12. package/helpers/mixed.mjs +2 -2
  13. package/package.json +1 -1
  14. package/pluginHooks.d.ts +6 -28
  15. package/pluginHooks.js +63 -117
  16. package/pluginHooks.mjs +63 -117
  17. package/plugins/copyPaste/clipboardData.js +18 -0
  18. package/plugins/copyPaste/clipboardData.mjs +14 -0
  19. package/plugins/copyPaste/copyPaste.js +92 -38
  20. package/plugins/copyPaste/copyPaste.mjs +94 -40
  21. package/plugins/copyPaste/pasteEvent.js +14 -0
  22. package/plugins/copyPaste/pasteEvent.mjs +9 -0
  23. package/plugins/mergeCells/mergeCells.js +14 -0
  24. package/plugins/mergeCells/mergeCells.mjs +14 -0
  25. package/plugins/nestedHeaders/nestedHeaders.js +22 -21
  26. package/plugins/nestedHeaders/nestedHeaders.mjs +22 -21
  27. package/utils/parseTable.js +83 -527
  28. package/utils/parseTable.mjs +82 -523
  29. package/plugins/copyPaste/clipboardData/clipboardData.js +0 -516
  30. package/plugins/copyPaste/clipboardData/clipboardData.mjs +0 -512
  31. package/plugins/copyPaste/clipboardData/copyClipboardData.js +0 -69
  32. package/plugins/copyPaste/clipboardData/copyClipboardData.mjs +0 -65
  33. package/plugins/copyPaste/clipboardData/index.js +0 -9
  34. package/plugins/copyPaste/clipboardData/index.mjs +0 -4
  35. package/plugins/copyPaste/clipboardData/pasteClipboardData.js +0 -81
  36. package/plugins/copyPaste/clipboardData/pasteClipboardData.mjs +0 -77
@@ -14,7 +14,8 @@ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!priva
14
14
  function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
15
15
  import { BasePlugin } from "../base/index.mjs";
16
16
  import Hooks from "../../pluginHooks.mjs";
17
- import { stringify } from "../../3rdparty/SheetClip/index.mjs";
17
+ import { stringify, parse } from "../../3rdparty/SheetClip/index.mjs";
18
+ import { arrayEach } from "../../helpers/array.mjs";
18
19
  import { sanitize } from "../../helpers/string.mjs";
19
20
  import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent } from "../../helpers/dom/element.mjs";
20
21
  import { isSafari } from "../../helpers/browser.mjs";
@@ -23,10 +24,10 @@ import copyColumnHeadersOnlyItem from "./contextMenuItem/copyColumnHeadersOnly.m
23
24
  import copyWithColumnGroupHeadersItem from "./contextMenuItem/copyWithColumnGroupHeaders.mjs";
24
25
  import copyWithColumnHeadersItem from "./contextMenuItem/copyWithColumnHeaders.mjs";
25
26
  import cutItem from "./contextMenuItem/cut.mjs";
27
+ import PasteEvent from "./pasteEvent.mjs";
26
28
  import { CopyableRangesFactory, normalizeRanges } from "./copyableRanges.mjs";
27
- import { getDataByCoords, getHTMLFromConfig } from "../../utils/parseTable.mjs";
29
+ import { _dataToHTML, htmlToGridSettings } from "../../utils/parseTable.mjs";
28
30
  import EventManager from "../../eventManager.mjs";
29
- import { CopyClipboardData, PasteClipboardData, META_HEAD } from "./clipboardData/index.mjs";
30
31
  Hooks.getSingleton().register('afterCopyLimit');
31
32
  Hooks.getSingleton().register('modifyCopyableRange');
32
33
  Hooks.getSingleton().register('beforeCut');
@@ -38,6 +39,7 @@ Hooks.getSingleton().register('afterCopy');
38
39
  export const PLUGIN_KEY = 'copyPaste';
39
40
  export const PLUGIN_PRIORITY = 80;
40
41
  const SETTING_KEYS = ['fragmentSelection'];
42
+ const META_HEAD = ['<meta name="generator" content="Handsontable"/>', '<style type="text/css">td{white-space:normal}br{mso-data-placement:same-cell}</style>'].join('');
41
43
 
42
44
  /* eslint-disable jsdoc/require-description-complete-sentence */
43
45
  /**
@@ -82,6 +84,7 @@ var _isTriggeredByCopy = /*#__PURE__*/new WeakMap();
82
84
  var _isTriggeredByCut = /*#__PURE__*/new WeakMap();
83
85
  var _copyableRangesFactory = /*#__PURE__*/new WeakMap();
84
86
  var _ensureClipboardEventsGetTriggered = /*#__PURE__*/new WeakSet();
87
+ var _countCopiedHeaders = /*#__PURE__*/new WeakSet();
85
88
  var _addContentEditableToHighlightedCell = /*#__PURE__*/new WeakSet();
86
89
  var _removeContentEditableFromHighlightedCell = /*#__PURE__*/new WeakSet();
87
90
  export class CopyPaste extends BasePlugin {
@@ -95,6 +98,15 @@ export class CopyPaste extends BasePlugin {
95
98
  * Add the `contenteditable` attribute to the highlighted cell and select its content.
96
99
  */
97
100
  _classPrivateMethodInitSpec(this, _addContentEditableToHighlightedCell);
101
+ /**
102
+ * Counts how many column headers will be copied based on the passed range.
103
+ *
104
+ * @private
105
+ * @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
106
+ * @returns {{ columnHeadersCount: number }} Returns an object with keys that holds
107
+ * information with the number of copied headers.
108
+ */
109
+ _classPrivateMethodInitSpec(this, _countCopiedHeaders);
98
110
  /**
99
111
  * Ensure that the `copy`/`cut` events get triggered properly in Safari.
100
112
  *
@@ -379,14 +391,26 @@ export class CopyPaste extends BasePlugin {
379
391
  * @returns {Array[]} An array of arrays that will be copied to the clipboard.
380
392
  */
381
393
  getRangedData(ranges) {
394
+ const data = [];
382
395
  const {
383
396
  rows,
384
397
  columns
385
398
  } = normalizeRanges(ranges);
386
- return getDataByCoords(this.hot, {
387
- rows,
388
- columns
399
+
400
+ // concatenate all rows and columns data defined in ranges into one copyable string
401
+ arrayEach(rows, row => {
402
+ const rowSet = [];
403
+ arrayEach(columns, column => {
404
+ if (row < 0) {
405
+ // `row` as the second argument acts here as the `headerLevel` argument
406
+ rowSet.push(this.hot.getColHeader(column, row));
407
+ } else {
408
+ rowSet.push(this.hot.getCopyableData(row, column));
409
+ }
410
+ });
411
+ data.push(rowSet);
389
412
  });
413
+ return data;
390
414
  }
391
415
 
392
416
  /**
@@ -403,17 +427,7 @@ export class CopyPaste extends BasePlugin {
403
427
  if (!pastableText && !pastableHtml) {
404
428
  return;
405
429
  }
406
- const pasteData = {
407
- clipboardData: {
408
- data: {},
409
- setData(type, value) {
410
- this.data[type] = value;
411
- },
412
- getData(type) {
413
- return this.data[type];
414
- }
415
- }
416
- };
430
+ const pasteData = new PasteEvent();
417
431
  if (pastableText) {
418
432
  pasteData.clipboardData.setData('text/plain', pastableText);
419
433
  }
@@ -552,7 +566,7 @@ export class CopyPaste extends BasePlugin {
552
566
  /**
553
567
  * `copy` event callback on textarea element.
554
568
  *
555
- * @param {ClipboardEvent} event ClipboardEvent.
569
+ * @param {Event} event ClipboardEvent.
556
570
  * @private
557
571
  */
558
572
  onCopy(event) {
@@ -561,12 +575,19 @@ export class CopyPaste extends BasePlugin {
561
575
  }
562
576
  this.setCopyableText();
563
577
  _classPrivateFieldSet(this, _isTriggeredByCopy, false);
564
- const copyClipboardData = new CopyClipboardData(this.hot, this.copyableRanges);
565
- const allowCopying = !!this.hot.runHooks('beforeCopy', copyClipboardData);
578
+ const data = this.getRangedData(this.copyableRanges);
579
+ const copiedHeadersCount = _classPrivateMethodGet(this, _countCopiedHeaders, _countCopiedHeaders2).call(this, this.copyableRanges);
580
+ const allowCopying = !!this.hot.runHooks('beforeCopy', data, this.copyableRanges, copiedHeadersCount);
566
581
  if (allowCopying) {
567
- event.clipboardData.setData('text/plain', stringify(copyClipboardData.getData()));
568
- event.clipboardData.setData('text/html', [copyClipboardData.getType() === 'handsontable' ? META_HEAD : '', getHTMLFromConfig(copyClipboardData.getMetaInfo())].join(''));
569
- this.hot.runHooks('afterCopy', copyClipboardData);
582
+ const textPlain = stringify(data);
583
+ if (event && event.clipboardData) {
584
+ const textHTML = _dataToHTML(data, this.hot.rootDocument);
585
+ event.clipboardData.setData('text/plain', textPlain);
586
+ event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
587
+ } else if (typeof ClipboardEvent === 'undefined') {
588
+ this.hot.rootWindow.clipboardData.setData('Text', textPlain);
589
+ }
590
+ this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
570
591
  }
571
592
  _classPrivateFieldSet(this, _copyMode, 'cells-only');
572
593
  event.preventDefault();
@@ -575,7 +596,7 @@ export class CopyPaste extends BasePlugin {
575
596
  /**
576
597
  * `cut` event callback on textarea element.
577
598
  *
578
- * @param {ClipboardEvent} event ClipboardEvent.
599
+ * @param {Event} event ClipboardEvent.
579
600
  * @private
580
601
  */
581
602
  onCut(event) {
@@ -584,13 +605,19 @@ export class CopyPaste extends BasePlugin {
584
605
  }
585
606
  this.setCopyableText();
586
607
  _classPrivateFieldSet(this, _isTriggeredByCut, false);
587
- const copyClipboardData = new CopyClipboardData(this.hot, this.copyableRanges);
588
- const allowCuttingOut = !!this.hot.runHooks('beforeCut', copyClipboardData);
608
+ const rangedData = this.getRangedData(this.copyableRanges);
609
+ const allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);
589
610
  if (allowCuttingOut) {
590
- event.clipboardData.setData('text/plain', stringify(copyClipboardData.getData()));
591
- event.clipboardData.setData('text/html', [copyClipboardData.getType() === 'handsontable' ? META_HEAD : '', getHTMLFromConfig(copyClipboardData.getMetaInfo())].join(''));
611
+ const textPlain = stringify(rangedData);
612
+ if (event && event.clipboardData) {
613
+ const textHTML = _dataToHTML(rangedData, this.hot.rootDocument);
614
+ event.clipboardData.setData('text/plain', textPlain);
615
+ event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
616
+ } else if (typeof ClipboardEvent === 'undefined') {
617
+ this.hot.rootWindow.clipboardData.setData('Text', textPlain);
618
+ }
592
619
  this.hot.emptySelectedCells('CopyPaste.cut');
593
- this.hot.runHooks('afterCut', copyClipboardData);
620
+ this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
594
621
  }
595
622
  event.preventDefault();
596
623
  }
@@ -608,22 +635,34 @@ export class CopyPaste extends BasePlugin {
608
635
  if (event && event.preventDefault) {
609
636
  event.preventDefault();
610
637
  }
611
- const html = sanitize(event.clipboardData.getData('text/html'), {
612
- ADD_TAGS: ['meta'],
613
- ADD_ATTR: ['content'],
614
- FORCE_BODY: true
615
- });
616
- const pasteClipboardData = new PasteClipboardData(event.clipboardData.getData('text/plain'), html);
617
- if (this.hot.runHooks('beforePaste', pasteClipboardData) === false) {
638
+ let pastedData;
639
+ if (event && typeof event.clipboardData !== 'undefined') {
640
+ const textHTML = sanitize(event.clipboardData.getData('text/html'), {
641
+ ADD_TAGS: ['meta'],
642
+ ADD_ATTR: ['content'],
643
+ FORCE_BODY: true
644
+ });
645
+ if (textHTML && /(<table)|(<TABLE)/g.test(textHTML)) {
646
+ const parsedConfig = htmlToGridSettings(textHTML, this.hot.rootDocument);
647
+ pastedData = parsedConfig.data;
648
+ } else {
649
+ pastedData = event.clipboardData.getData('text/plain');
650
+ }
651
+ } else if (typeof ClipboardEvent === 'undefined' && typeof this.hot.rootWindow.clipboardData !== 'undefined') {
652
+ pastedData = this.hot.rootWindow.clipboardData.getData('Text');
653
+ }
654
+ if (typeof pastedData === 'string') {
655
+ pastedData = parse(pastedData);
656
+ }
657
+ if (pastedData === void 0 || pastedData && pastedData.length === 0) {
618
658
  return;
619
659
  }
620
- const pastedTable = pasteClipboardData.getData();
621
- if (pastedTable.length === 0) {
660
+ if (this.hot.runHooks('beforePaste', pastedData, this.copyableRanges) === false) {
622
661
  return;
623
662
  }
624
- const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedTable);
663
+ const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedData);
625
664
  this.hot.selectCell(startRow, startColumn, Math.min(this.hot.countRows() - 1, endRow), Math.min(this.hot.countCols() - 1, endColumn));
626
- this.hot.runHooks('afterPaste', pasteClipboardData);
665
+ this.hot.runHooks('afterPaste', pastedData, this.copyableRanges);
627
666
  }
628
667
 
629
668
  /**
@@ -719,6 +758,21 @@ function _ensureClipboardEventsGetTriggered2(eventName) {
719
758
  this.hot.rootDocument.execCommand(eventName);
720
759
  }
721
760
  }
761
+ function _countCopiedHeaders2(ranges) {
762
+ const {
763
+ rows
764
+ } = normalizeRanges(ranges);
765
+ let columnHeadersCount = 0;
766
+ for (let row = 0; row < rows.length; row++) {
767
+ if (rows[row] >= 0) {
768
+ break;
769
+ }
770
+ columnHeadersCount += 1;
771
+ }
772
+ return {
773
+ columnHeadersCount
774
+ };
775
+ }
722
776
  function _addContentEditableToHighlightedCell2() {
723
777
  if (this.hot.isListening()) {
724
778
  const lastSelectedRange = this.hot.getSelectedRangeLast();
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ var _clipboardData = _interopRequireDefault(require("./clipboardData"));
5
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+ /**
7
+ * @private
8
+ */
9
+ class PasteEvent {
10
+ constructor() {
11
+ this.clipboardData = new _clipboardData.default();
12
+ }
13
+ }
14
+ exports.default = PasteEvent;
@@ -0,0 +1,9 @@
1
+ import ClipboardData from "./clipboardData.mjs";
2
+ /**
3
+ * @private
4
+ */
5
+ export default class PasteEvent {
6
+ constructor() {
7
+ this.clipboardData = new ClipboardData();
8
+ }
9
+ }
@@ -186,6 +186,9 @@ class MergeCells extends _base.BasePlugin {
186
186
  this.addHook('afterDrawSelection', function () {
187
187
  return _this.onAfterDrawSelection(...arguments);
188
188
  });
189
+ this.addHook('beforeRemoveCellClassNames', function () {
190
+ return _this.onBeforeRemoveCellClassNames(...arguments);
191
+ });
189
192
  this.addHook('beforeUndoStackChange', (action, source) => {
190
193
  if (source === 'MergeCells') {
191
194
  return false;
@@ -1197,5 +1200,16 @@ class MergeCells extends _base.BasePlugin {
1197
1200
  }
1198
1201
  return this.selectionCalculations.getSelectedMergedCellClassName(currentRow, currentColumn, cornersOfSelection, layerLevel);
1199
1202
  }
1203
+
1204
+ /**
1205
+ * `beforeRemoveCellClassNames` hook callback. Used to remove additional class name from all cells in the table.
1206
+ *
1207
+ * @private
1208
+ * @returns {string[]} An `Array` of `String`s. Each of these strings will act like class names to be removed from
1209
+ * all the cells in the table.
1210
+ */
1211
+ onBeforeRemoveCellClassNames() {
1212
+ return this.selectionCalculations.getSelectedMergedCellClassNameToRemove();
1213
+ }
1200
1214
  }
1201
1215
  exports.MergeCells = MergeCells;
@@ -182,6 +182,9 @@ export class MergeCells extends BasePlugin {
182
182
  this.addHook('afterDrawSelection', function () {
183
183
  return _this.onAfterDrawSelection(...arguments);
184
184
  });
185
+ this.addHook('beforeRemoveCellClassNames', function () {
186
+ return _this.onBeforeRemoveCellClassNames(...arguments);
187
+ });
185
188
  this.addHook('beforeUndoStackChange', (action, source) => {
186
189
  if (source === 'MergeCells') {
187
190
  return false;
@@ -1193,4 +1196,15 @@ export class MergeCells extends BasePlugin {
1193
1196
  }
1194
1197
  return this.selectionCalculations.getSelectedMergedCellClassName(currentRow, currentColumn, cornersOfSelection, layerLevel);
1195
1198
  }
1199
+
1200
+ /**
1201
+ * `beforeRemoveCellClassNames` hook callback. Used to remove additional class name from all cells in the table.
1202
+ *
1203
+ * @private
1204
+ * @returns {string[]} An `Array` of `String`s. Each of these strings will act like class names to be removed from
1205
+ * all the cells in the table.
1206
+ */
1207
+ onBeforeRemoveCellClassNames() {
1208
+ return this.selectionCalculations.getSelectedMergedCellClassNameToRemove();
1209
+ }
1196
1210
  }
@@ -529,44 +529,45 @@ class NestedHeaders extends _base.BasePlugin {
529
529
  * of the column.
530
530
  *
531
531
  * @private
532
- * @param {object} clipboardData Information about already performed copy action.
533
- * @param {Function} clipboardData.removeRow Remove row from the copied/pasted dataset.
534
- * @param {Function} clipboardData.removeColumn Remove column from the copied/pasted dataset.
535
- * @param {Function} clipboardData.insertAtRow Insert values at row index.
536
- * @param {Function} clipboardData.insertAtColumn Insert values at column index.
537
- * @param {Function} clipboardData.setCellAt Change headers or cells in the copied/pasted dataset.
538
- * @param {Function} clipboardData.getCellAt Get headers or cells from the copied/pasted dataset.
539
- * @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
540
- * @param {Function} clipboardData.getMetaInfo Gets grid settings for copied data.
541
- * @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
532
+ * @param {Array[]} data An array of arrays which contains data to copied.
533
+ * @param {object[]} copyableRanges An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
534
+ * which will copied.
535
+ * @param {{ columnHeadersCount: number }} copiedHeadersCount An object with keys that holds information with
536
+ * the number of copied headers.
542
537
  */
543
- onBeforeCopy(clipboardData) {
544
- const copyableRanges = clipboardData.getRanges();
545
- for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex += 1) {
538
+ onBeforeCopy(data, copyableRanges, _ref2) {
539
+ let {
540
+ columnHeadersCount
541
+ } = _ref2;
542
+ if (columnHeadersCount === 0) {
543
+ return;
544
+ }
545
+ for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex++) {
546
546
  const {
547
547
  startRow,
548
548
  startCol,
549
549
  endRow,
550
550
  endCol
551
551
  } = copyableRanges[rangeIndex];
552
+ const rowsCount = endRow - startRow + 1;
552
553
  const columnsCount = startCol - endCol + 1;
553
554
 
554
555
  // do not process dataset ranges and column headers where only one column is copied
555
556
  if (startRow >= 0 || columnsCount === 1) {
556
557
  break;
557
558
  }
558
- for (let column = startCol; column <= endCol; column += 1) {
559
- for (let row = startRow; row <= endRow; row += 1) {
560
- var _classPrivateFieldGet4, _classPrivateFieldGet5;
559
+ for (let column = startCol; column <= endCol; column++) {
560
+ for (let row = startRow; row <= endRow; row++) {
561
+ var _classPrivateFieldGet4;
562
+ const zeroBasedColumnHeaderLevel = rowsCount + row;
561
563
  const zeroBasedColumnIndex = column - startCol;
562
564
  if (zeroBasedColumnIndex === 0) {
563
565
  continue; // eslint-disable-line no-continue
564
566
  }
565
567
 
566
568
  const isRoot = (_classPrivateFieldGet4 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4.isRoot;
567
- const collapsible = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet5 === void 0 ? void 0 : _classPrivateFieldGet5.collapsible;
568
- if (collapsible === true && isRoot === false) {
569
- clipboardData.setCellAt(row, zeroBasedColumnIndex, '');
569
+ if (isRoot === false) {
570
+ data[zeroBasedColumnHeaderLevel][zeroBasedColumnIndex] = '';
570
571
  }
571
572
  }
572
573
  }
@@ -869,10 +870,10 @@ class NestedHeaders extends _base.BasePlugin {
869
870
  * @returns {string} Returns the column header value to update.
870
871
  */
871
872
  onModifyColumnHeaderValue(value, visualColumnIndex, headerLevel) {
872
- var _classPrivateFieldGet6;
873
+ var _classPrivateFieldGet5;
873
874
  const {
874
875
  label
875
- } = (_classPrivateFieldGet6 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet6 !== void 0 ? _classPrivateFieldGet6 : {
876
+ } = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet5 !== void 0 ? _classPrivateFieldGet5 : {
876
877
  label: ''
877
878
  };
878
879
  return label;
@@ -525,44 +525,45 @@ export class NestedHeaders extends BasePlugin {
525
525
  * of the column.
526
526
  *
527
527
  * @private
528
- * @param {object} clipboardData Information about already performed copy action.
529
- * @param {Function} clipboardData.removeRow Remove row from the copied/pasted dataset.
530
- * @param {Function} clipboardData.removeColumn Remove column from the copied/pasted dataset.
531
- * @param {Function} clipboardData.insertAtRow Insert values at row index.
532
- * @param {Function} clipboardData.insertAtColumn Insert values at column index.
533
- * @param {Function} clipboardData.setCellAt Change headers or cells in the copied/pasted dataset.
534
- * @param {Function} clipboardData.getCellAt Get headers or cells from the copied/pasted dataset.
535
- * @param {Function} clipboardData.getData Gets copied data stored as array of arrays.
536
- * @param {Function} clipboardData.getMetaInfo Gets grid settings for copied data.
537
- * @param {Function} clipboardData.getRanges Returns ranges related to copied part of Handsontable.
528
+ * @param {Array[]} data An array of arrays which contains data to copied.
529
+ * @param {object[]} copyableRanges An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
530
+ * which will copied.
531
+ * @param {{ columnHeadersCount: number }} copiedHeadersCount An object with keys that holds information with
532
+ * the number of copied headers.
538
533
  */
539
- onBeforeCopy(clipboardData) {
540
- const copyableRanges = clipboardData.getRanges();
541
- for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex += 1) {
534
+ onBeforeCopy(data, copyableRanges, _ref2) {
535
+ let {
536
+ columnHeadersCount
537
+ } = _ref2;
538
+ if (columnHeadersCount === 0) {
539
+ return;
540
+ }
541
+ for (let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex++) {
542
542
  const {
543
543
  startRow,
544
544
  startCol,
545
545
  endRow,
546
546
  endCol
547
547
  } = copyableRanges[rangeIndex];
548
+ const rowsCount = endRow - startRow + 1;
548
549
  const columnsCount = startCol - endCol + 1;
549
550
 
550
551
  // do not process dataset ranges and column headers where only one column is copied
551
552
  if (startRow >= 0 || columnsCount === 1) {
552
553
  break;
553
554
  }
554
- for (let column = startCol; column <= endCol; column += 1) {
555
- for (let row = startRow; row <= endRow; row += 1) {
556
- var _classPrivateFieldGet4, _classPrivateFieldGet5;
555
+ for (let column = startCol; column <= endCol; column++) {
556
+ for (let row = startRow; row <= endRow; row++) {
557
+ var _classPrivateFieldGet4;
558
+ const zeroBasedColumnHeaderLevel = rowsCount + row;
557
559
  const zeroBasedColumnIndex = column - startCol;
558
560
  if (zeroBasedColumnIndex === 0) {
559
561
  continue; // eslint-disable-line no-continue
560
562
  }
561
563
 
562
564
  const isRoot = (_classPrivateFieldGet4 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4.isRoot;
563
- const collapsible = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(row, column)) === null || _classPrivateFieldGet5 === void 0 ? void 0 : _classPrivateFieldGet5.collapsible;
564
- if (collapsible === true && isRoot === false) {
565
- clipboardData.setCellAt(row, zeroBasedColumnIndex, '');
565
+ if (isRoot === false) {
566
+ data[zeroBasedColumnHeaderLevel][zeroBasedColumnIndex] = '';
566
567
  }
567
568
  }
568
569
  }
@@ -865,10 +866,10 @@ export class NestedHeaders extends BasePlugin {
865
866
  * @returns {string} Returns the column header value to update.
866
867
  */
867
868
  onModifyColumnHeaderValue(value, visualColumnIndex, headerLevel) {
868
- var _classPrivateFieldGet6;
869
+ var _classPrivateFieldGet5;
869
870
  const {
870
871
  label
871
- } = (_classPrivateFieldGet6 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet6 !== void 0 ? _classPrivateFieldGet6 : {
872
+ } = (_classPrivateFieldGet5 = _classPrivateFieldGet(this, _stateManager).getHeaderTreeNodeData(headerLevel, visualColumnIndex)) !== null && _classPrivateFieldGet5 !== void 0 ? _classPrivateFieldGet5 : {
872
873
  label: ''
873
874
  };
874
875
  return label;