@odoo/o-spreadsheet 16.2.3 → 16.2.5

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.
@@ -1008,6 +1008,10 @@ function deepEquals(o1, o2) {
1008
1008
  }
1009
1009
  return true;
1010
1010
  }
1011
+ /** Check if the given array contains all the values of the other array. */
1012
+ function includesAll(arr, values) {
1013
+ return values.every((value) => arr.includes(value));
1014
+ }
1011
1015
  /**
1012
1016
  * Return an object with all the keys in the object that have a falsy value removed.
1013
1017
  */
@@ -1681,12 +1685,77 @@ const numberRepresentation = [];
1681
1685
  * - all digit stored in the decimal part of the number
1682
1686
  *
1683
1687
  * The 'maxDecimal' parameter allows to indicate the number of digits to not
1684
- * exceed in the decimal part, in which case digits are rounded
1688
+ * exceed in the decimal part, in which case digits are rounded.
1685
1689
  *
1686
- * Intl.Numberformat is used to properly handle all the roundings.
1687
- * e.g. 1234.7 with format ### (<> maxDecimals=0) should become 1235, not 1234
1688
1690
  **/
1689
1691
  function splitNumber(value, maxDecimals = MAX_DECIMAL_PLACES) {
1692
+ const asString = value.toString();
1693
+ if (asString.includes("e"))
1694
+ return splitNumberIntl(value, maxDecimals);
1695
+ if (Number.isInteger(value)) {
1696
+ return { integerDigits: asString, decimalDigits: undefined };
1697
+ }
1698
+ const indexOfDot = asString.indexOf(".");
1699
+ let integerDigits = asString.substring(0, indexOfDot);
1700
+ let decimalDigits = asString.substring(indexOfDot + 1);
1701
+ if (maxDecimals === 0) {
1702
+ if (Number(decimalDigits[0]) >= 5) {
1703
+ integerDigits = (Number(integerDigits) + 1).toString();
1704
+ }
1705
+ return { integerDigits, decimalDigits: undefined };
1706
+ }
1707
+ if (decimalDigits.length > maxDecimals) {
1708
+ const { integerDigits: roundedIntegerDigits, decimalDigits: roundedDecimalDigits } = limitDecimalDigits(decimalDigits, maxDecimals);
1709
+ decimalDigits = roundedDecimalDigits;
1710
+ if (roundedIntegerDigits !== "0") {
1711
+ integerDigits = (Number(integerDigits) + Number(roundedIntegerDigits)).toString();
1712
+ }
1713
+ }
1714
+ return { integerDigits, decimalDigits: removeTrailingZeroes(decimalDigits || "") };
1715
+ }
1716
+ /**
1717
+ * Return the given string minus the trailing "0" characters.
1718
+ *
1719
+ * @param numberString : a string of integers
1720
+ * @returns the numberString, minus the eventual zeroes at the end
1721
+ */
1722
+ function removeTrailingZeroes(numberString) {
1723
+ let i = numberString.length - 1;
1724
+ while (i >= 0 && numberString[i] === "0") {
1725
+ i--;
1726
+ }
1727
+ return numberString.slice(0, i + 1) || undefined;
1728
+ }
1729
+ /**
1730
+ * Limit the size of the decimal part of a number to the given number of digits.
1731
+ */
1732
+ function limitDecimalDigits(decimalDigits, maxDecimals) {
1733
+ let integerDigits = "0";
1734
+ let resultDecimalDigits = decimalDigits;
1735
+ // Note : we'd want to simply use number.toFixed() to handle the max digits & rounding,
1736
+ // but it has very strange behaviour. Ex: 12.345.toFixed(2) => "12.35", but 1.345.toFixed(2) => "1.34"
1737
+ let slicedDecimalDigits = decimalDigits.slice(0, maxDecimals);
1738
+ const i = maxDecimals;
1739
+ if (Number(Number(decimalDigits[i]) < 5)) {
1740
+ return { integerDigits, decimalDigits: slicedDecimalDigits };
1741
+ }
1742
+ // round up
1743
+ const slicedRoundedUp = (Number(slicedDecimalDigits) + 1).toString();
1744
+ if (slicedRoundedUp.length > slicedDecimalDigits.length) {
1745
+ integerDigits = (Number(integerDigits) + 1).toString();
1746
+ resultDecimalDigits = undefined;
1747
+ }
1748
+ else {
1749
+ resultDecimalDigits = slicedRoundedUp;
1750
+ }
1751
+ return { integerDigits, decimalDigits: resultDecimalDigits };
1752
+ }
1753
+ /**
1754
+ * Split numbers into decimal/integer digits using Intl.NumberFormat.
1755
+ * Supports numbers with a lot of digits that are transformed to scientific notation by
1756
+ * number.toString(), but is slow.
1757
+ */
1758
+ function splitNumberIntl(value, maxDecimals = MAX_DECIMAL_PLACES) {
1690
1759
  let formatter = numberRepresentation[maxDecimals];
1691
1760
  if (!formatter) {
1692
1761
  formatter = new Intl.NumberFormat("en-US", {
@@ -4204,6 +4273,8 @@ exports.CommandResult = void 0;
4204
4273
  CommandResult[CommandResult["InvalidSelectionStep"] = 83] = "InvalidSelectionStep";
4205
4274
  CommandResult[CommandResult["DuplicatedChartId"] = 84] = "DuplicatedChartId";
4206
4275
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4276
+ CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4277
+ CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4207
4278
  })(exports.CommandResult || (exports.CommandResult = {}));
4208
4279
 
4209
4280
  var DIRECTION;
@@ -9135,6 +9206,11 @@ colMenuRegistry
9135
9206
  name: REMOVE_COLUMNS_NAME,
9136
9207
  sequence: 90,
9137
9208
  action: REMOVE_COLUMNS_ACTION,
9209
+ isVisible: (env) => {
9210
+ const sheetId = env.model.getters.getActiveSheetId();
9211
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
9212
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9213
+ },
9138
9214
  })
9139
9215
  .add("clear_column", {
9140
9216
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -9147,9 +9223,8 @@ colMenuRegistry
9147
9223
  action: HIDE_COLUMNS_ACTION,
9148
9224
  isVisible: (env) => {
9149
9225
  const sheetId = env.model.getters.getActiveSheetId();
9150
- const hiddenCols = env.model.getters.getHiddenColsGroups(sheetId).flat();
9151
- return (env.model.getters.getNumberCols(sheetId) >
9152
- hiddenCols.length + env.model.getters.getElementsFromSelection("COL").length);
9226
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
9227
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9153
9228
  },
9154
9229
  separator: true,
9155
9230
  })
@@ -9223,6 +9298,11 @@ rowMenuRegistry
9223
9298
  name: REMOVE_ROWS_NAME,
9224
9299
  sequence: 70,
9225
9300
  action: REMOVE_ROWS_ACTION,
9301
+ isVisible: (env) => {
9302
+ const sheetId = env.model.getters.getActiveSheetId();
9303
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
9304
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
9305
+ },
9226
9306
  })
9227
9307
  .add("clear_row", {
9228
9308
  name: DELETE_CONTENT_ROWS_NAME,
@@ -9235,9 +9315,8 @@ rowMenuRegistry
9235
9315
  action: HIDE_ROWS_ACTION,
9236
9316
  isVisible: (env) => {
9237
9317
  const sheetId = env.model.getters.getActiveSheetId();
9238
- const hiddenRows = env.model.getters.getHiddenRowsGroups(sheetId).flat();
9239
- return (env.model.getters.getNumberRows(sheetId) >
9240
- hiddenRows.length + env.model.getters.getElementsFromSelection("ROW").length);
9318
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
9319
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
9241
9320
  },
9242
9321
  separator: true,
9243
9322
  })
@@ -21973,8 +22052,8 @@ class Grid extends owl.Component {
21973
22052
  },
21974
22053
  "CTRL+END": () => {
21975
22054
  const sheetId = this.env.model.getters.getActiveSheetId();
21976
- const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", range(0, this.env.model.getters.getNumberCols(sheetId)).reverse());
21977
- const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", range(0, this.env.model.getters.getNumberRows(sheetId)).reverse());
22055
+ const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", this.env.model.getters.getNumberCols(sheetId) - 1, 0);
22056
+ const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", this.env.model.getters.getNumberRows(sheetId) - 1, 0);
21978
22057
  this.env.model.selection.selectCell(col, row);
21979
22058
  },
21980
22059
  "SHIFT+ ": () => {
@@ -22054,9 +22133,10 @@ class Grid extends owl.Component {
22054
22133
  this.focus();
22055
22134
  }
22056
22135
  focus() {
22136
+ var _a;
22057
22137
  if (!this.env.model.getters.getSelectedFigureId() &&
22058
22138
  this.env.model.getters.getEditionMode() === "inactive") {
22059
- this.hiddenInput.el.focus();
22139
+ (_a = this.hiddenInput.el) === null || _a === void 0 ? void 0 : _a.focus();
22060
22140
  }
22061
22141
  }
22062
22142
  get gridEl() {
@@ -25951,7 +26031,7 @@ function load(data, verboseImport) {
25951
26031
  }
25952
26032
  }
25953
26033
  }
25954
- data = JSON.parse(JSON.stringify(data));
26034
+ data = deepCopy(data);
25955
26035
  // apply migrations, if needed
25956
26036
  if ("version" in data) {
25957
26037
  if (data.version < CURRENT_VERSION) {
@@ -29394,7 +29474,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
29394
29474
  allowDispatch(cmd) {
29395
29475
  switch (cmd.type) {
29396
29476
  case "HIDE_COLUMNS_ROWS": {
29397
- if (!this.hiddenHeaders[cmd.sheetId]) {
29477
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29398
29478
  return 27 /* CommandResult.InvalidSheetId */;
29399
29479
  }
29400
29480
  const hiddenGroup = cmd.dimension === "COL"
@@ -29403,10 +29483,25 @@ class HeaderVisibilityPlugin extends CorePlugin {
29403
29483
  const elements = cmd.dimension === "COL"
29404
29484
  ? this.getters.getNumberCols(cmd.sheetId)
29405
29485
  : this.getters.getNumberRows(cmd.sheetId);
29406
- return (hiddenGroup || []).flat().concat(cmd.elements).length < elements
29407
- ? 0 /* CommandResult.Success */
29408
- : 66 /* CommandResult.TooManyHiddenElements */;
29486
+ const hiddenElements = new Set((hiddenGroup || []).flat().concat(cmd.elements));
29487
+ if (hiddenElements.size >= elements) {
29488
+ return 66 /* CommandResult.TooManyHiddenElements */;
29489
+ }
29490
+ else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
29491
+ return 86 /* CommandResult.InvalidHeaderIndex */;
29492
+ }
29493
+ else {
29494
+ return 0 /* CommandResult.Success */;
29495
+ }
29409
29496
  }
29497
+ case "REMOVE_COLUMNS_ROWS":
29498
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29499
+ return 27 /* CommandResult.InvalidSheetId */;
29500
+ }
29501
+ if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29502
+ return 8 /* CommandResult.NotEnoughElements */;
29503
+ }
29504
+ return 0 /* CommandResult.Success */;
29410
29505
  }
29411
29506
  return 0 /* CommandResult.Success */;
29412
29507
  }
@@ -29453,6 +29548,10 @@ class HeaderVisibilityPlugin extends CorePlugin {
29453
29548
  }
29454
29549
  return;
29455
29550
  }
29551
+ canRemoveHeaders(sheetId, dimension, elements) {
29552
+ const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
29553
+ return !includesAll(elements, visibleHeaders);
29554
+ }
29456
29555
  isRowHiddenByUser(sheetId, index) {
29457
29556
  return this.hiddenHeaders[sheetId].ROW[index];
29458
29557
  }
@@ -29497,6 +29596,9 @@ class HeaderVisibilityPlugin extends CorePlugin {
29497
29596
  }
29498
29597
  return consecutiveIndexes;
29499
29598
  }
29599
+ getAllVisibleHeaders(sheetId, dimension) {
29600
+ return range(0, this.hiddenHeaders[sheetId][dimension].length).filter((i) => !this.hiddenHeaders[sheetId][dimension][i]);
29601
+ }
29500
29602
  import(data) {
29501
29603
  var _a, _b;
29502
29604
  for (let sheet of data.sheets) {
@@ -29544,6 +29646,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
29544
29646
  }
29545
29647
  }
29546
29648
  HeaderVisibilityPlugin.getters = [
29649
+ "canRemoveHeaders",
29547
29650
  "getHiddenColsGroups",
29548
29651
  "getHiddenRowsGroups",
29549
29652
  "isRowHiddenByUser",
@@ -30562,13 +30665,27 @@ class SheetPlugin extends CorePlugin {
30562
30665
  return this.orderedSheetIds.length > 1
30563
30666
  ? 0 /* CommandResult.Success */
30564
30667
  : 9 /* CommandResult.NotEnoughSheets */;
30668
+ case "ADD_COLUMNS_ROWS":
30669
+ const elements = cmd.dimension === "COL"
30670
+ ? this.getNumberCols(cmd.sheetId)
30671
+ : this.getNumberRows(cmd.sheetId);
30672
+ if (cmd.base < 0 || cmd.base > elements) {
30673
+ return 86 /* CommandResult.InvalidHeaderIndex */;
30674
+ }
30675
+ else if (cmd.quantity <= 0) {
30676
+ return 87 /* CommandResult.InvalidQuantity */;
30677
+ }
30678
+ return 0 /* CommandResult.Success */;
30565
30679
  case "REMOVE_COLUMNS_ROWS": {
30566
- const length = cmd.dimension === "COL"
30680
+ const elements = cmd.dimension === "COL"
30567
30681
  ? this.getNumberCols(cmd.sheetId)
30568
30682
  : this.getNumberRows(cmd.sheetId);
30569
- return length > cmd.elements.length
30570
- ? 0 /* CommandResult.Success */
30571
- : 8 /* CommandResult.NotEnoughElements */;
30683
+ if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
30684
+ return 86 /* CommandResult.InvalidHeaderIndex */;
30685
+ }
30686
+ else {
30687
+ return 0 /* CommandResult.Success */;
30688
+ }
30572
30689
  }
30573
30690
  case "FREEZE_ROWS": {
30574
30691
  return this.checkValidations(cmd, this.checkRowFreezeQuantity, this.checkRowFreezeOverlapMerge);
@@ -31036,7 +31153,7 @@ class SheetPlugin extends CorePlugin {
31036
31153
  duplicateSheet(fromId, toId) {
31037
31154
  const sheet = this.getSheet(fromId);
31038
31155
  const toName = this.getDuplicateSheetName(sheet.name);
31039
- const newSheet = JSON.parse(JSON.stringify(sheet));
31156
+ const newSheet = deepCopy(sheet);
31040
31157
  newSheet.id = toId;
31041
31158
  newSheet.name = toName;
31042
31159
  for (let col = 0; col <= newSheet.numberOfCols; col++) {
@@ -31163,10 +31280,10 @@ class SheetPlugin extends CorePlugin {
31163
31280
  }
31164
31281
  }
31165
31282
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
31166
- for (let [index, row] of Object.entries(sheet.rows)) {
31167
- const rowIndex = parseInt(index, 10);
31283
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31284
+ const row = sheet.rows[rowIndex];
31168
31285
  for (let i in row.cells) {
31169
- const colIndex = parseInt(i, 10);
31286
+ const colIndex = Number(i);
31170
31287
  const cellId = row.cells[i];
31171
31288
  if (cellId) {
31172
31289
  if (colIndex === deletedColumn) {
@@ -31193,11 +31310,11 @@ class SheetPlugin extends CorePlugin {
31193
31310
  */
31194
31311
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
31195
31312
  const commands = [];
31196
- for (const [index, row] of Object.entries(sheet.rows)) {
31197
- const rowIndex = parseInt(index, 10);
31313
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31314
+ const row = sheet.rows[rowIndex];
31198
31315
  if (dimension !== "rows" || rowIndex >= addedElement) {
31199
31316
  for (let i in row.cells) {
31200
- const colIndex = parseInt(i, 10);
31317
+ const colIndex = Number(i);
31201
31318
  const cellId = row.cells[i];
31202
31319
  if (cellId) {
31203
31320
  if (dimension === "rows" || colIndex >= addedElement) {
@@ -31227,11 +31344,11 @@ class SheetPlugin extends CorePlugin {
31227
31344
  */
31228
31345
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
31229
31346
  const numberRows = deleteToRow - deleteFromRow + 1;
31230
- for (let [index, row] of Object.entries(sheet.rows)) {
31231
- const rowIndex = parseInt(index, 10);
31347
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31348
+ const row = sheet.rows[rowIndex];
31232
31349
  if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
31233
31350
  for (let i in row.cells) {
31234
- const colIndex = parseInt(i, 10);
31351
+ const colIndex = Number(i);
31235
31352
  const cellId = row.cells[i];
31236
31353
  if (cellId) {
31237
31354
  this.dispatch("CLEAR_CELL", {
@@ -31244,7 +31361,7 @@ class SheetPlugin extends CorePlugin {
31244
31361
  }
31245
31362
  if (rowIndex > deleteToRow) {
31246
31363
  for (let i in row.cells) {
31247
- const colIndex = parseInt(i, 10);
31364
+ const colIndex = Number(i);
31248
31365
  const cellId = row.cells[i];
31249
31366
  if (cellId) {
31250
31367
  this.dispatch("UPDATE_CELL_POSITION", {
@@ -31262,7 +31379,7 @@ class SheetPlugin extends CorePlugin {
31262
31379
  const rows = [];
31263
31380
  const cellsQueue = sheet.rows.map((row) => row.cells);
31264
31381
  for (let i in sheet.rows) {
31265
- if (parseInt(i, 10) === index) {
31382
+ if (Number(i) === index) {
31266
31383
  continue;
31267
31384
  }
31268
31385
  rows.push({
@@ -32433,13 +32550,11 @@ class FilterEvaluationPlugin extends UIPlugin {
32433
32550
  return Boolean(id && ((_b = (_a = this.filterValues[sheetId]) === null || _a === void 0 ? void 0 : _a[id]) === null || _b === void 0 ? void 0 : _b.length));
32434
32551
  }
32435
32552
  intersectZoneWithViewport(sheetId, zone) {
32436
- const colsRange = range(zone.left, zone.right + 1);
32437
- const rowsRange = range(zone.top, zone.bottom + 1);
32438
32553
  return {
32439
- left: this.getters.findVisibleHeader(sheetId, "COL", colsRange),
32440
- right: this.getters.findVisibleHeader(sheetId, "COL", colsRange.reverse()),
32441
- top: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange),
32442
- bottom: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange.reverse()),
32554
+ left: this.getters.findVisibleHeader(sheetId, "COL", zone.left, zone.right),
32555
+ right: this.getters.findVisibleHeader(sheetId, "COL", zone.right, zone.left),
32556
+ top: this.getters.findVisibleHeader(sheetId, "ROW", zone.top, zone.bottom),
32557
+ bottom: this.getters.findVisibleHeader(sheetId, "ROW", zone.bottom, zone.top),
32443
32558
  };
32444
32559
  }
32445
32560
  updateFilter({ col, row, values, sheetId }) {
@@ -34546,13 +34661,33 @@ class HeaderVisibilityUIPlugin extends UIPlugin {
34546
34661
  getNextVisibleCellPosition({ sheetId, col, row }) {
34547
34662
  return {
34548
34663
  sheetId,
34549
- col: this.findVisibleHeader(sheetId, "COL", range(col, this.getters.getNumberCols(sheetId))),
34550
- row: this.findVisibleHeader(sheetId, "ROW", range(row, this.getters.getNumberRows(sheetId))),
34664
+ col: this.findVisibleHeader(sheetId, "COL", col, this.getters.getNumberCols(sheetId) - 1),
34665
+ row: this.findVisibleHeader(sheetId, "ROW", row, this.getters.getNumberRows(sheetId) - 1),
34551
34666
  };
34552
34667
  }
34553
- findVisibleHeader(sheetId, dimension, indexes) {
34554
- return indexes.find((index) => this.getters.doesHeaderExist(sheetId, dimension, index) &&
34555
- !this.isHeaderHidden(sheetId, dimension, index));
34668
+ /**
34669
+ * Find the first visible header in the range [`from` => `to`].
34670
+ *
34671
+ * Both `from` and `to` are inclusive.
34672
+ */
34673
+ findVisibleHeader(sheetId, dimension, from, to) {
34674
+ if (from <= to) {
34675
+ for (let i = from; i <= to; i++) {
34676
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
34677
+ !this.isHeaderHidden(sheetId, dimension, i)) {
34678
+ return i;
34679
+ }
34680
+ }
34681
+ }
34682
+ if (from > to) {
34683
+ for (let i = from; i >= to; i--) {
34684
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
34685
+ !this.isHeaderHidden(sheetId, dimension, i)) {
34686
+ return i;
34687
+ }
34688
+ }
34689
+ }
34690
+ return undefined;
34556
34691
  }
34557
34692
  findLastVisibleColRowIndex(sheetId, dimension, { last, first }) {
34558
34693
  const lastVisibleIndex = range(last, first, -1).find((index) => !this.isHeaderHidden(sheetId, dimension, index));
@@ -34560,7 +34695,7 @@ class HeaderVisibilityUIPlugin extends UIPlugin {
34560
34695
  }
34561
34696
  findFirstVisibleColRowIndex(sheetId, dimension) {
34562
34697
  const numberOfHeaders = this.getters.getNumberHeaders(sheetId, dimension);
34563
- for (let i = 0; i < numberOfHeaders - 1; i++) {
34698
+ for (let i = 0; i < numberOfHeaders; i++) {
34564
34699
  if (dimension === "COL" && !this.isColHidden(sheetId, i)) {
34565
34700
  return i;
34566
34701
  }
@@ -42764,8 +42899,8 @@ class SelectionStreamProcessorImpl {
42764
42899
  }
42765
42900
  const { left, right, top, bottom } = zone;
42766
42901
  const sheetId = this.getters.getActiveSheetId();
42767
- const refCol = this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1));
42768
- const refRow = this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1));
42902
+ const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
42903
+ const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
42769
42904
  if (refRow === undefined || refCol === undefined) {
42770
42905
  return 17 /* CommandResult.SelectionOutOfBound */;
42771
42906
  }
@@ -42840,10 +42975,10 @@ class SelectionStreamProcessorImpl {
42840
42975
  const { col: anchorCol, row: anchorRow } = anchor.cell;
42841
42976
  return {
42842
42977
  col: this.getters.isColHidden(sheetId, anchorCol)
42843
- ? this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1)) || anchorCol
42978
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
42844
42979
  : anchorCol,
42845
42980
  row: this.getters.isRowHidden(sheetId, anchorRow)
42846
- ? this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1)) || anchorRow
42981
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
42847
42982
  : anchorRow,
42848
42983
  };
42849
42984
  }
@@ -44593,6 +44728,8 @@ class Model extends EventBus {
44593
44728
  * Internal status of the model. Important for command handling coordination
44594
44729
  */
44595
44730
  this.status = 0 /* Status.Ready */;
44731
+ this.handlers = [];
44732
+ this.coreHandlers = [];
44596
44733
  /**
44597
44734
  * The dispatch method is the only entry point to manipulate data in the model.
44598
44735
  * This is through this method that commands are dispatched most of the time
@@ -44697,6 +44834,8 @@ class Model extends EventBus {
44697
44834
  this.uuidGenerator.setIsFastStrategy(true);
44698
44835
  // Initiate stream processor
44699
44836
  this.selection = new SelectionStreamProcessorImpl(this.getters);
44837
+ this.coreHandlers.push(this.range);
44838
+ this.handlers.push(this.range);
44700
44839
  this.corePluginConfig = this.setupCorePluginConfig();
44701
44840
  this.uiPluginConfig = this.setupUiPluginConfig();
44702
44841
  // registering plugins
@@ -44705,15 +44844,23 @@ class Model extends EventBus {
44705
44844
  }
44706
44845
  Object.assign(this.getters, this.coreGetters);
44707
44846
  for (let Plugin of statefulUIPluginRegistry.getAll()) {
44708
- this.statefulUIPlugins.push(this.setupUiPlugin(Plugin));
44847
+ const plugin = this.setupUiPlugin(Plugin);
44848
+ this.statefulUIPlugins.push(plugin);
44849
+ this.handlers.push(plugin);
44709
44850
  }
44710
44851
  for (let Plugin of coreViewsPluginRegistry.getAll()) {
44711
- this.coreViewsPlugins.push(this.setupUiPlugin(Plugin));
44852
+ const plugin = this.setupUiPlugin(Plugin);
44853
+ this.coreViewsPlugins.push(plugin);
44854
+ this.handlers.push(plugin);
44855
+ this.coreHandlers.push(plugin);
44712
44856
  }
44713
44857
  for (let Plugin of featurePluginRegistry.getAll()) {
44714
- this.featurePlugins.push(this.setupUiPlugin(Plugin));
44858
+ const plugin = this.setupUiPlugin(Plugin);
44859
+ this.featurePlugins.push(plugin);
44860
+ this.handlers.push(plugin);
44715
44861
  }
44716
44862
  this.uuidGenerator.setIsFastStrategy(false);
44863
+ this.handlers.push(this.history);
44717
44864
  // starting plugins
44718
44865
  this.dispatch("START");
44719
44866
  // Model should be the last permanent subscriber in the list since he should render
@@ -44735,12 +44882,6 @@ class Model extends EventBus {
44735
44882
  // by owl, since we do not rely on reactivity
44736
44883
  owl.markRaw(this);
44737
44884
  }
44738
- get handlers() {
44739
- return [this.range, ...this.corePlugins, ...this.allUIPlugins, this.history];
44740
- }
44741
- get allUIPlugins() {
44742
- return [...this.statefulUIPlugins, ...this.coreViewsPlugins, ...this.featurePlugins];
44743
- }
44744
44885
  joinSession() {
44745
44886
  this.session.join(this.config.client);
44746
44887
  }
@@ -44782,6 +44923,8 @@ class Model extends EventBus {
44782
44923
  }
44783
44924
  plugin.import(data);
44784
44925
  this.corePlugins.push(plugin);
44926
+ this.coreHandlers.push(plugin);
44927
+ this.handlers.push(plugin);
44785
44928
  }
44786
44929
  onRemoteRevisionReceived({ commands }) {
44787
44930
  for (let command of commands) {
@@ -44924,7 +45067,7 @@ class Model extends EventBus {
44924
45067
  }
44925
45068
  }
44926
45069
  data.revisionId = this.session.getRevisionId() || DEFAULT_REVISION_ID;
44927
- data = JSON.parse(JSON.stringify(data));
45070
+ data = deepCopy(data);
44928
45071
  return data;
44929
45072
  }
44930
45073
  updateMode(mode) {
@@ -44952,7 +45095,7 @@ class Model extends EventBus {
44952
45095
  handler.exportForExcel(data);
44953
45096
  }
44954
45097
  }
44955
- data = JSON.parse(JSON.stringify(data));
45098
+ data = deepCopy(data);
44956
45099
  return getXLSX(data);
44957
45100
  }
44958
45101
  garbageCollectExternalResources() {
@@ -45092,6 +45235,6 @@ exports.setTranslationMethod = setTranslationMethod;
45092
45235
  exports.tokenize = tokenize;
45093
45236
 
45094
45237
 
45095
- __info__.version = '16.2.3';
45096
- __info__.date = '2023-04-14T12:47:50.453Z';
45097
- __info__.hash = '4514375';
45238
+ __info__.version = '16.2.5';
45239
+ __info__.date = '2023-04-28T12:25:41.422Z';
45240
+ __info__.hash = 'cc60a52';
@@ -984,9 +984,9 @@ declare class Model extends EventBus<any> implements CommandDispatcher {
984
984
  */
985
985
  private coreGetters;
986
986
  uuidGenerator: UuidGenerator;
987
+ private readonly handlers;
988
+ private readonly coreHandlers;
987
989
  constructor(data?: any, config?: Partial<ModelConfig>, stateUpdateMessages?: StateUpdateMessage[], uuidGenerator?: UuidGenerator, verboseImport?: boolean);
988
- get handlers(): CommandHandler<Command>[];
989
- get allUIPlugins(): UIPlugin[];
990
990
  joinSession(): void;
991
991
  leaveSession(): void;
992
992
  private setupUiPlugin;
@@ -2135,7 +2135,9 @@ declare const enum CommandResult {
2135
2135
  DuplicatedFigureId = 82,
2136
2136
  InvalidSelectionStep = 83,
2137
2137
  DuplicatedChartId = 84,
2138
- ChartDoesNotExist = 85
2138
+ ChartDoesNotExist = 85,
2139
+ InvalidHeaderIndex = 86,
2140
+ InvalidQuantity = 87
2139
2141
  }
2140
2142
  interface CommandHandler<T> {
2141
2143
  allowDispatch(command: T): CommandResult | CommandResult[];
@@ -3384,14 +3386,16 @@ declare class HeaderSizePlugin extends CorePlugin<HeaderSizeState> implements He
3384
3386
  }
3385
3387
 
3386
3388
  declare class HeaderVisibilityPlugin extends CorePlugin {
3387
- static getters: readonly ["getHiddenColsGroups", "getHiddenRowsGroups", "isRowHiddenByUser", "isColHiddenByUser"];
3389
+ static getters: readonly ["canRemoveHeaders", "getHiddenColsGroups", "getHiddenRowsGroups", "isRowHiddenByUser", "isColHiddenByUser"];
3388
3390
  private readonly hiddenHeaders;
3389
- allowDispatch(cmd: Command): CommandResult.Success | CommandResult.InvalidSheetId | CommandResult.TooManyHiddenElements;
3391
+ allowDispatch(cmd: Command): CommandResult.Success | CommandResult.NotEnoughElements | CommandResult.InvalidSheetId | CommandResult.TooManyHiddenElements | CommandResult.InvalidHeaderIndex;
3390
3392
  handle(cmd: Command): void;
3393
+ canRemoveHeaders(sheetId: UID, dimension: Dimension, elements: HeaderIndex[]): boolean;
3391
3394
  isRowHiddenByUser(sheetId: UID, index: HeaderIndex): boolean;
3392
3395
  isColHiddenByUser(sheetId: UID, index: HeaderIndex): boolean;
3393
3396
  getHiddenColsGroups(sheetId: UID): ConsecutiveIndexes[];
3394
3397
  getHiddenRowsGroups(sheetId: UID): ConsecutiveIndexes[];
3398
+ private getAllVisibleHeaders;
3395
3399
  import(data: WorkbookData): void;
3396
3400
  exportForExcel(data: ExcelWorkbookData): void;
3397
3401
  export(data: WorkbookData): void;
@@ -4199,7 +4203,12 @@ declare class HeaderVisibilityUIPlugin extends UIPlugin {
4199
4203
  isColHidden(sheetId: UID, index: number): boolean;
4200
4204
  isHeaderHidden(sheetId: UID, dimension: Dimension, index: number): boolean;
4201
4205
  getNextVisibleCellPosition({ sheetId, col, row }: CellPosition): CellPosition;
4202
- findVisibleHeader(sheetId: UID, dimension: Dimension, indexes: number[]): number | undefined;
4206
+ /**
4207
+ * Find the first visible header in the range [`from` => `to`].
4208
+ *
4209
+ * Both `from` and `to` are inclusive.
4210
+ */
4211
+ findVisibleHeader(sheetId: UID, dimension: Dimension, from: number, to: number): number | undefined;
4203
4212
  findLastVisibleColRowIndex(sheetId: UID, dimension: Dimension, { last, first }: {
4204
4213
  first: HeaderIndex;
4205
4214
  last: HeaderIndex;