@odoo/o-spreadsheet 16.0.7 → 16.0.9

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.
@@ -1024,6 +1024,10 @@
1024
1024
  }
1025
1025
  return true;
1026
1026
  }
1027
+ /** Check if the given array contains all the values of the other array. */
1028
+ function includesAll(arr, values) {
1029
+ return values.every((value) => arr.includes(value));
1030
+ }
1027
1031
  /**
1028
1032
  * Return an object with all the keys in the object that have a falsy value removed.
1029
1033
  */
@@ -1569,12 +1573,77 @@
1569
1573
  * - all digit stored in the decimal part of the number
1570
1574
  *
1571
1575
  * The 'maxDecimal' parameter allows to indicate the number of digits to not
1572
- * exceed in the decimal part, in which case digits are rounded
1576
+ * exceed in the decimal part, in which case digits are rounded.
1573
1577
  *
1574
- * Intl.Numberformat is used to properly handle all the roundings.
1575
- * e.g. 1234.7 with format ### (<> maxDecimals=0) should become 1235, not 1234
1576
1578
  **/
1577
1579
  function splitNumber(value, maxDecimals = MAX_DECIMAL_PLACES) {
1580
+ const asString = value.toString();
1581
+ if (asString.includes("e"))
1582
+ return splitNumberIntl(value, maxDecimals);
1583
+ if (Number.isInteger(value)) {
1584
+ return { integerDigits: asString, decimalDigits: undefined };
1585
+ }
1586
+ const indexOfDot = asString.indexOf(".");
1587
+ let integerDigits = asString.substring(0, indexOfDot);
1588
+ let decimalDigits = asString.substring(indexOfDot + 1);
1589
+ if (maxDecimals === 0) {
1590
+ if (Number(decimalDigits[0]) >= 5) {
1591
+ integerDigits = (Number(integerDigits) + 1).toString();
1592
+ }
1593
+ return { integerDigits, decimalDigits: undefined };
1594
+ }
1595
+ if (decimalDigits.length > maxDecimals) {
1596
+ const { integerDigits: roundedIntegerDigits, decimalDigits: roundedDecimalDigits } = limitDecimalDigits(decimalDigits, maxDecimals);
1597
+ decimalDigits = roundedDecimalDigits;
1598
+ if (roundedIntegerDigits !== "0") {
1599
+ integerDigits = (Number(integerDigits) + Number(roundedIntegerDigits)).toString();
1600
+ }
1601
+ }
1602
+ return { integerDigits, decimalDigits: removeTrailingZeroes(decimalDigits || "") };
1603
+ }
1604
+ /**
1605
+ * Return the given string minus the trailing "0" characters.
1606
+ *
1607
+ * @param numberString : a string of integers
1608
+ * @returns the numberString, minus the eventual zeroes at the end
1609
+ */
1610
+ function removeTrailingZeroes(numberString) {
1611
+ let i = numberString.length - 1;
1612
+ while (i >= 0 && numberString[i] === "0") {
1613
+ i--;
1614
+ }
1615
+ return numberString.slice(0, i + 1) || undefined;
1616
+ }
1617
+ /**
1618
+ * Limit the size of the decimal part of a number to the given number of digits.
1619
+ */
1620
+ function limitDecimalDigits(decimalDigits, maxDecimals) {
1621
+ let integerDigits = "0";
1622
+ let resultDecimalDigits = decimalDigits;
1623
+ // Note : we'd want to simply use number.toFixed() to handle the max digits & rounding,
1624
+ // but it has very strange behaviour. Ex: 12.345.toFixed(2) => "12.35", but 1.345.toFixed(2) => "1.34"
1625
+ let slicedDecimalDigits = decimalDigits.slice(0, maxDecimals);
1626
+ const i = maxDecimals;
1627
+ if (Number(Number(decimalDigits[i]) < 5)) {
1628
+ return { integerDigits, decimalDigits: slicedDecimalDigits };
1629
+ }
1630
+ // round up
1631
+ const slicedRoundedUp = (Number(slicedDecimalDigits) + 1).toString();
1632
+ if (slicedRoundedUp.length > slicedDecimalDigits.length) {
1633
+ integerDigits = (Number(integerDigits) + 1).toString();
1634
+ resultDecimalDigits = undefined;
1635
+ }
1636
+ else {
1637
+ resultDecimalDigits = slicedRoundedUp;
1638
+ }
1639
+ return { integerDigits, decimalDigits: resultDecimalDigits };
1640
+ }
1641
+ /**
1642
+ * Split numbers into decimal/integer digits using Intl.NumberFormat.
1643
+ * Supports numbers with a lot of digits that are transformed to scientific notation by
1644
+ * number.toString(), but is slow.
1645
+ */
1646
+ function splitNumberIntl(value, maxDecimals = MAX_DECIMAL_PLACES) {
1578
1647
  let formatter = numberRepresentation[maxDecimals];
1579
1648
  if (!formatter) {
1580
1649
  formatter = new Intl.NumberFormat("en-US", {
@@ -3201,6 +3270,8 @@
3201
3270
  CommandResult[CommandResult["InvalidSelectionStep"] = 82] = "InvalidSelectionStep";
3202
3271
  CommandResult[CommandResult["DuplicatedChartId"] = 83] = "DuplicatedChartId";
3203
3272
  CommandResult[CommandResult["ChartDoesNotExist"] = 84] = "ChartDoesNotExist";
3273
+ CommandResult[CommandResult["InvalidHeaderIndex"] = 85] = "InvalidHeaderIndex";
3274
+ CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
3204
3275
  })(exports.CommandResult || (exports.CommandResult = {}));
3205
3276
 
3206
3277
  var DIRECTION;
@@ -3971,13 +4042,16 @@
3971
4042
  }
3972
4043
  });
3973
4044
  }
4045
+ get visibleMenuItems() {
4046
+ return this.props.menuItems.filter((x) => x.isVisible(this.env));
4047
+ }
3974
4048
  get subMenuPosition() {
3975
4049
  const position = Object.assign({}, this.subMenu.position);
3976
4050
  position.y -= this.subMenu.scrollOffset || 0;
3977
4051
  return position;
3978
4052
  }
3979
4053
  get menuHeight() {
3980
- return this.menuComponentHeight(this.props.menuItems);
4054
+ return this.menuComponentHeight(this.visibleMenuItems);
3981
4055
  }
3982
4056
  get subMenuHeight() {
3983
4057
  return this.menuComponentHeight(this.subMenu.menuItems);
@@ -4013,7 +4087,7 @@
4013
4087
  * and the menu item at a given index.
4014
4088
  */
4015
4089
  subMenuVerticalPosition(position) {
4016
- const menusAbove = this.props.menuItems.slice(0, position);
4090
+ const menusAbove = this.visibleMenuItems.slice(0, position);
4017
4091
  return this.menuComponentHeight(menusAbove) + this.position.y;
4018
4092
  }
4019
4093
  onExternalClick(ev) {
@@ -5546,6 +5620,11 @@
5546
5620
  name: REMOVE_COLUMNS_NAME,
5547
5621
  sequence: 90,
5548
5622
  action: REMOVE_COLUMNS_ACTION,
5623
+ isVisible: (env) => {
5624
+ const sheetId = env.model.getters.getActiveSheetId();
5625
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
5626
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
5627
+ },
5549
5628
  })
5550
5629
  .add("clear_column", {
5551
5630
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -5558,9 +5637,8 @@
5558
5637
  action: HIDE_COLUMNS_ACTION,
5559
5638
  isVisible: (env) => {
5560
5639
  const sheetId = env.model.getters.getActiveSheetId();
5561
- const hiddenCols = env.model.getters.getHiddenColsGroups(sheetId).flat();
5562
- return (env.model.getters.getNumberCols(sheetId) >
5563
- hiddenCols.length + env.model.getters.getElementsFromSelection("COL").length);
5640
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
5641
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
5564
5642
  },
5565
5643
  separator: true,
5566
5644
  })
@@ -5634,6 +5712,11 @@
5634
5712
  name: REMOVE_ROWS_NAME,
5635
5713
  sequence: 70,
5636
5714
  action: REMOVE_ROWS_ACTION,
5715
+ isVisible: (env) => {
5716
+ const sheetId = env.model.getters.getActiveSheetId();
5717
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
5718
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
5719
+ },
5637
5720
  })
5638
5721
  .add("clear_row", {
5639
5722
  name: DELETE_CONTENT_ROWS_NAME,
@@ -5646,9 +5729,8 @@
5646
5729
  action: HIDE_ROWS_ACTION,
5647
5730
  isVisible: (env) => {
5648
5731
  const sheetId = env.model.getters.getActiveSheetId();
5649
- const hiddenRows = env.model.getters.getHiddenRowsGroups(sheetId).flat();
5650
- return (env.model.getters.getNumberRows(sheetId) >
5651
- hiddenRows.length + env.model.getters.getElementsFromSelection("ROW").length);
5732
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
5733
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
5652
5734
  },
5653
5735
  separator: true,
5654
5736
  })
@@ -10310,7 +10392,7 @@
10310
10392
  openContextMenu(position) {
10311
10393
  const registry = this.getMenuItemRegistry();
10312
10394
  this.menuState.isOpen = true;
10313
- this.menuState.menuItems = registry.getAll().filter((x) => x.isVisible(this.env));
10395
+ this.menuState.menuItems = registry.getAll();
10314
10396
  this.menuState.position = position;
10315
10397
  }
10316
10398
  get chartComponent() {
@@ -17328,7 +17410,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
17328
17410
  base (number) ${_lt("The number to raise to the exponent power.")}
17329
17411
  exponent (number) ${_lt("The exponent to raise base to.")}
17330
17412
  `),
17331
- returns: ["BOOLEAN"],
17413
+ returns: ["NUMBER"],
17332
17414
  compute: function (base, exponent) {
17333
17415
  return POWER.compute(base, exponent);
17334
17416
  },
@@ -19830,14 +19912,31 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19830
19912
  * */
19831
19913
  getCurrentSelection() {
19832
19914
  let { startElement, endElement, startSelectionOffset, endSelectionOffset } = this.getStartAndEndSelection();
19833
- let startSizeBefore = this.findSizeBeforeElement(startElement);
19834
- let endSizeBefore = this.findSizeBeforeElement(endElement);
19915
+ let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
19916
+ let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
19835
19917
  return {
19836
- start: startSizeBefore + startSelectionOffset,
19837
- end: endSizeBefore + endSelectionOffset,
19918
+ start: startSizeBefore,
19919
+ end: endSizeBefore,
19838
19920
  };
19839
19921
  }
19840
- findSizeBeforeElement(nodeToFind) {
19922
+ /**
19923
+ * Computes the text 'index' inside this.el based on the currently selected node and its offset.
19924
+ * The selected node is either a Text node or an Element node.
19925
+ *
19926
+ * case 1 -Text node:
19927
+ * the offset is the number of characters from the start of the node. We have to add this offset to the
19928
+ * content length of all previous nodes.
19929
+ *
19930
+ * case 2 - Element node:
19931
+ * the offset is the number of child nodes before the selected node. We have to add the content length of
19932
+ * all the bnodes prior to the selected node as well as the content of the child node before the offset.
19933
+ *
19934
+ * See the MDN documentation for more details.
19935
+ * https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
19936
+ * https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
19937
+ *
19938
+ */
19939
+ findSelectionIndex(nodeToFind, nodeOffset) {
19841
19940
  let it = this.iterateChildren(this.el);
19842
19941
  let usedCharacters = 0;
19843
19942
  let current = it.next();
@@ -19849,6 +19948,19 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19849
19948
  }
19850
19949
  current = it.next();
19851
19950
  }
19951
+ if (current.value === nodeToFind) {
19952
+ if (!current.value.hasChildNodes()) {
19953
+ usedCharacters += nodeOffset;
19954
+ }
19955
+ else {
19956
+ const children = [...current.value.childNodes].slice(0, nodeOffset);
19957
+ for (const child of children) {
19958
+ if (!child.textContent)
19959
+ continue;
19960
+ usedCharacters += child.textContent.length;
19961
+ }
19962
+ }
19963
+ }
19852
19964
  return usedCharacters;
19853
19965
  }
19854
19966
  getStartAndEndSelection() {
@@ -22334,8 +22446,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22334
22446
  },
22335
22447
  "CTRL+END": () => {
22336
22448
  const sheetId = this.env.model.getters.getActiveSheetId();
22337
- const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", range(0, this.env.model.getters.getNumberCols(sheetId)).reverse());
22338
- const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", range(0, this.env.model.getters.getNumberRows(sheetId)).reverse());
22449
+ const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", this.env.model.getters.getNumberCols(sheetId) - 1, 0);
22450
+ const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", this.env.model.getters.getNumberRows(sheetId) - 1, 0);
22339
22451
  this.env.model.selection.selectCell(col, row);
22340
22452
  },
22341
22453
  "SHIFT+ ": () => {
@@ -22411,9 +22523,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22411
22523
  this.focus();
22412
22524
  }
22413
22525
  focus() {
22526
+ var _a;
22414
22527
  if (!this.env.model.getters.getSelectedFigureId() &&
22415
22528
  this.env.model.getters.getEditionMode() === "inactive") {
22416
- this.hiddenInput.el.focus();
22529
+ (_a = this.hiddenInput.el) === null || _a === void 0 ? void 0 : _a.focus();
22417
22530
  }
22418
22531
  }
22419
22532
  get gridEl() {
@@ -22617,9 +22730,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22617
22730
  this.closeOpenedPopover();
22618
22731
  this.menuState.isOpen = true;
22619
22732
  this.menuState.position = { x, y };
22620
- this.menuState.menuItems = registries$1[type]
22621
- .getAll()
22622
- .filter((item) => !item.isVisible || item.isVisible(this.env));
22733
+ this.menuState.menuItems = registries$1[type].getAll();
22623
22734
  }
22624
22735
  copy(cut, ev) {
22625
22736
  if (!this.gridEl.contains(document.activeElement)) {
@@ -24243,7 +24354,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
24243
24354
  if (cell.style) {
24244
24355
  style = data.styles[cell.style];
24245
24356
  }
24246
- const format = cell.format ? data.formats[cell.format] : undefined;
24357
+ const format = extractFormat(cell, data);
24247
24358
  const exportedBorder = {};
24248
24359
  if (cell.border) {
24249
24360
  const border = data.borders[cell.border];
@@ -24277,6 +24388,22 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
24277
24388
  styles.font["italic"] = !!(style === null || style === void 0 ? void 0 : style.italic) || undefined;
24278
24389
  return styles;
24279
24390
  }
24391
+ function extractFormat(cell, data) {
24392
+ if (cell.format) {
24393
+ return data.formats[cell.format];
24394
+ }
24395
+ if (cell.isFormula) {
24396
+ const tokens = tokenize(cell.content || "");
24397
+ const functions = functionRegistry.content;
24398
+ const isExported = tokens
24399
+ .filter((tk) => tk.type === "FUNCTION")
24400
+ .every((tk) => functions[tk.value.toUpperCase()].isExported);
24401
+ if (!isExported) {
24402
+ return cell.computedFormat;
24403
+ }
24404
+ }
24405
+ return undefined;
24406
+ }
24280
24407
  function normalizeStyle(construct, styles) {
24281
24408
  const { id: fontId } = pushElement(styles["font"], construct.fonts);
24282
24409
  const { id: fillId } = pushElement(styles["fill"], construct.fills);
@@ -26357,7 +26484,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
26357
26484
  }
26358
26485
  }
26359
26486
  }
26360
- data = JSON.parse(JSON.stringify(data));
26487
+ data = deepCopy(data);
26361
26488
  // apply migrations, if needed
26362
26489
  if ("version" in data) {
26363
26490
  if (data.version < CURRENT_VERSION) {
@@ -27499,6 +27626,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
27499
27626
  const exportedCellData = sheet.cells[xc];
27500
27627
  exportedCellData.value = cell.evaluated.value;
27501
27628
  exportedCellData.isFormula = cell.isFormula();
27629
+ if (cell.format !== cell.evaluated.format) {
27630
+ exportedCellData.computedFormat = cell.evaluated.format;
27631
+ }
27502
27632
  }
27503
27633
  }
27504
27634
  }
@@ -28942,7 +29072,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28942
29072
  allowDispatch(cmd) {
28943
29073
  switch (cmd.type) {
28944
29074
  case "HIDE_COLUMNS_ROWS": {
28945
- if (!this.hiddenHeaders[cmd.sheetId]) {
29075
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
28946
29076
  return 27 /* CommandResult.InvalidSheetId */;
28947
29077
  }
28948
29078
  const hiddenGroup = cmd.dimension === "COL"
@@ -28951,10 +29081,25 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28951
29081
  const elements = cmd.dimension === "COL"
28952
29082
  ? this.getters.getNumberCols(cmd.sheetId)
28953
29083
  : this.getters.getNumberRows(cmd.sheetId);
28954
- return (hiddenGroup || []).flat().concat(cmd.elements).length < elements
28955
- ? 0 /* CommandResult.Success */
28956
- : 65 /* CommandResult.TooManyHiddenElements */;
29084
+ const hiddenElements = new Set((hiddenGroup || []).flat().concat(cmd.elements));
29085
+ if (hiddenElements.size >= elements) {
29086
+ return 65 /* CommandResult.TooManyHiddenElements */;
29087
+ }
29088
+ else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
29089
+ return 85 /* CommandResult.InvalidHeaderIndex */;
29090
+ }
29091
+ else {
29092
+ return 0 /* CommandResult.Success */;
29093
+ }
28957
29094
  }
29095
+ case "REMOVE_COLUMNS_ROWS":
29096
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29097
+ return 27 /* CommandResult.InvalidSheetId */;
29098
+ }
29099
+ if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29100
+ return 8 /* CommandResult.NotEnoughElements */;
29101
+ }
29102
+ return 0 /* CommandResult.Success */;
28958
29103
  }
28959
29104
  return 0 /* CommandResult.Success */;
28960
29105
  }
@@ -29001,6 +29146,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29001
29146
  }
29002
29147
  return;
29003
29148
  }
29149
+ canRemoveHeaders(sheetId, dimension, elements) {
29150
+ const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
29151
+ return !includesAll(elements, visibleHeaders);
29152
+ }
29004
29153
  isRowHiddenByUser(sheetId, index) {
29005
29154
  return this.hiddenHeaders[sheetId].ROW[index];
29006
29155
  }
@@ -29045,6 +29194,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29045
29194
  }
29046
29195
  return consecutiveIndexes;
29047
29196
  }
29197
+ getAllVisibleHeaders(sheetId, dimension) {
29198
+ return range(0, this.hiddenHeaders[sheetId][dimension].length).filter((i) => !this.hiddenHeaders[sheetId][dimension][i]);
29199
+ }
29048
29200
  import(data) {
29049
29201
  var _a, _b;
29050
29202
  for (let sheet of data.sheets) {
@@ -29092,6 +29244,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29092
29244
  }
29093
29245
  }
29094
29246
  HeaderVisibilityPlugin.getters = [
29247
+ "canRemoveHeaders",
29095
29248
  "getHiddenColsGroups",
29096
29249
  "getHiddenRowsGroups",
29097
29250
  "isRowHiddenByUser",
@@ -29592,13 +29745,27 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29592
29745
  return this.orderedSheetIds.length > 1
29593
29746
  ? 0 /* CommandResult.Success */
29594
29747
  : 9 /* CommandResult.NotEnoughSheets */;
29748
+ case "ADD_COLUMNS_ROWS":
29749
+ const elements = cmd.dimension === "COL"
29750
+ ? this.getNumberCols(cmd.sheetId)
29751
+ : this.getNumberRows(cmd.sheetId);
29752
+ if (cmd.base < 0 || cmd.base > elements) {
29753
+ return 85 /* CommandResult.InvalidHeaderIndex */;
29754
+ }
29755
+ else if (cmd.quantity <= 0) {
29756
+ return 86 /* CommandResult.InvalidQuantity */;
29757
+ }
29758
+ return 0 /* CommandResult.Success */;
29595
29759
  case "REMOVE_COLUMNS_ROWS": {
29596
- const length = cmd.dimension === "COL"
29760
+ const elements = cmd.dimension === "COL"
29597
29761
  ? this.getNumberCols(cmd.sheetId)
29598
29762
  : this.getNumberRows(cmd.sheetId);
29599
- return length > cmd.elements.length
29600
- ? 0 /* CommandResult.Success */
29601
- : 8 /* CommandResult.NotEnoughElements */;
29763
+ if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
29764
+ return 85 /* CommandResult.InvalidHeaderIndex */;
29765
+ }
29766
+ else {
29767
+ return 0 /* CommandResult.Success */;
29768
+ }
29602
29769
  }
29603
29770
  case "FREEZE_ROWS": {
29604
29771
  return this.checkValidations(cmd, this.checkRowFreezeQuantity, this.checkRowFreezeOverlapMerge);
@@ -30083,7 +30250,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30083
30250
  duplicateSheet(fromId, toId) {
30084
30251
  const sheet = this.getSheet(fromId);
30085
30252
  const toName = this.getDuplicateSheetName(sheet.name);
30086
- const newSheet = JSON.parse(JSON.stringify(sheet));
30253
+ const newSheet = deepCopy(sheet);
30087
30254
  newSheet.id = toId;
30088
30255
  newSheet.name = toName;
30089
30256
  for (let col = 0; col <= newSheet.numberOfCols; col++) {
@@ -30210,10 +30377,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30210
30377
  }
30211
30378
  }
30212
30379
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
30213
- for (let [index, row] of Object.entries(sheet.rows)) {
30214
- const rowIndex = parseInt(index, 10);
30380
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
30381
+ const row = sheet.rows[rowIndex];
30215
30382
  for (let i in row.cells) {
30216
- const colIndex = parseInt(i, 10);
30383
+ const colIndex = Number(i);
30217
30384
  const cellId = row.cells[i];
30218
30385
  if (cellId) {
30219
30386
  if (colIndex === deletedColumn) {
@@ -30240,11 +30407,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30240
30407
  */
30241
30408
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
30242
30409
  const commands = [];
30243
- for (const [index, row] of Object.entries(sheet.rows)) {
30244
- const rowIndex = parseInt(index, 10);
30410
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
30411
+ const row = sheet.rows[rowIndex];
30245
30412
  if (dimension !== "rows" || rowIndex >= addedElement) {
30246
30413
  for (let i in row.cells) {
30247
- const colIndex = parseInt(i, 10);
30414
+ const colIndex = Number(i);
30248
30415
  const cellId = row.cells[i];
30249
30416
  if (cellId) {
30250
30417
  if (dimension === "rows" || colIndex >= addedElement) {
@@ -30274,11 +30441,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30274
30441
  */
30275
30442
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
30276
30443
  const numberRows = deleteToRow - deleteFromRow + 1;
30277
- for (let [index, row] of Object.entries(sheet.rows)) {
30278
- const rowIndex = parseInt(index, 10);
30444
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
30445
+ const row = sheet.rows[rowIndex];
30279
30446
  if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
30280
30447
  for (let i in row.cells) {
30281
- const colIndex = parseInt(i, 10);
30448
+ const colIndex = Number(i);
30282
30449
  const cellId = row.cells[i];
30283
30450
  if (cellId) {
30284
30451
  this.dispatch("CLEAR_CELL", {
@@ -30291,7 +30458,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30291
30458
  }
30292
30459
  if (rowIndex > deleteToRow) {
30293
30460
  for (let i in row.cells) {
30294
- const colIndex = parseInt(i, 10);
30461
+ const colIndex = Number(i);
30295
30462
  const cellId = row.cells[i];
30296
30463
  if (cellId) {
30297
30464
  this.dispatch("UPDATE_CELL_POSITION", {
@@ -30309,7 +30476,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30309
30476
  const rows = [];
30310
30477
  const cellsQueue = sheet.rows.map((row) => row.cells);
30311
30478
  for (let i in sheet.rows) {
30312
- if (parseInt(i, 10) === index) {
30479
+ if (Number(i) === index) {
30313
30480
  continue;
30314
30481
  }
30315
30482
  rows.push({
@@ -32945,13 +33112,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32945
33112
  return Boolean(id && ((_b = (_a = this.filterValues[sheetId]) === null || _a === void 0 ? void 0 : _a[id]) === null || _b === void 0 ? void 0 : _b.length));
32946
33113
  }
32947
33114
  intersectZoneWithViewport(sheetId, zone) {
32948
- const colsRange = range(zone.left, zone.right + 1);
32949
- const rowsRange = range(zone.top, zone.bottom + 1);
32950
33115
  return {
32951
- left: this.getters.findVisibleHeader(sheetId, "COL", colsRange),
32952
- right: this.getters.findVisibleHeader(sheetId, "COL", colsRange.reverse()),
32953
- top: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange),
32954
- bottom: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange.reverse()),
33116
+ left: this.getters.findVisibleHeader(sheetId, "COL", zone.left, zone.right),
33117
+ right: this.getters.findVisibleHeader(sheetId, "COL", zone.right, zone.left),
33118
+ top: this.getters.findVisibleHeader(sheetId, "ROW", zone.top, zone.bottom),
33119
+ bottom: this.getters.findVisibleHeader(sheetId, "ROW", zone.bottom, zone.top),
32955
33120
  };
32956
33121
  }
32957
33122
  updateFilter({ col, row, values, sheetId }) {
@@ -33393,13 +33558,33 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33393
33558
  }
33394
33559
  getNextVisibleCellPosition(sheetId, col, row) {
33395
33560
  return {
33396
- col: this.findVisibleHeader(sheetId, "COL", range(col, this.getters.getNumberCols(sheetId))),
33397
- row: this.findVisibleHeader(sheetId, "ROW", range(row, this.getters.getNumberRows(sheetId))),
33561
+ col: this.findVisibleHeader(sheetId, "COL", col, this.getters.getNumberCols(sheetId) - 1),
33562
+ row: this.findVisibleHeader(sheetId, "ROW", row, this.getters.getNumberRows(sheetId) - 1),
33398
33563
  };
33399
33564
  }
33400
- findVisibleHeader(sheetId, dimension, indexes) {
33401
- return indexes.find((index) => this.getters.doesHeaderExist(sheetId, dimension, index) &&
33402
- !this.isHeaderHidden(sheetId, dimension, index));
33565
+ /**
33566
+ * Find the first visible header in the range [`from` => `to`].
33567
+ *
33568
+ * Both `from` and `to` are inclusive.
33569
+ */
33570
+ findVisibleHeader(sheetId, dimension, from, to) {
33571
+ if (from <= to) {
33572
+ for (let i = from; i <= to; i++) {
33573
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
33574
+ !this.isHeaderHidden(sheetId, dimension, i)) {
33575
+ return i;
33576
+ }
33577
+ }
33578
+ }
33579
+ if (from > to) {
33580
+ for (let i = from; i >= to; i--) {
33581
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
33582
+ !this.isHeaderHidden(sheetId, dimension, i)) {
33583
+ return i;
33584
+ }
33585
+ }
33586
+ }
33587
+ return undefined;
33403
33588
  }
33404
33589
  findLastVisibleColRowIndex(sheetId, dimension, indexes) {
33405
33590
  let lastIndex;
@@ -33412,7 +33597,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33412
33597
  }
33413
33598
  findFirstVisibleColRowIndex(sheetId, dimension) {
33414
33599
  const numberOfHeaders = this.getters.getNumberHeaders(sheetId, dimension);
33415
- for (let i = 0; i < numberOfHeaders - 1; i++) {
33600
+ for (let i = 0; i < numberOfHeaders; i++) {
33416
33601
  if (dimension === "COL" && !this.isColHidden(sheetId, i)) {
33417
33602
  return i;
33418
33603
  }
@@ -37539,7 +37724,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
37539
37724
  }
37540
37725
  openContextMenu(x, y, registry, menuId) {
37541
37726
  this.menuState.isOpen = true;
37542
- this.menuState.menuItems = registry.getAll().filter((x) => x.isVisible(this.env));
37727
+ this.menuState.menuItems = registry.getAll();
37543
37728
  this.menuState.position = { x, y };
37544
37729
  this.menuState.menuId = menuId;
37545
37730
  }
@@ -38300,7 +38485,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
38300
38485
  const { left, top, height } = ev.target.getBoundingClientRect();
38301
38486
  this.state.menuState.isOpen = true;
38302
38487
  this.state.menuState.position = { x: left, y: top + height };
38303
- this.state.menuState.menuItems = getMenuChildren(menu, this.env).filter((item) => !item.isVisible || item.isVisible(this.env));
38488
+ this.state.menuState.menuItems = getMenuChildren(menu, this.env);
38304
38489
  this.state.menuState.parentMenu = menu;
38305
38490
  this.isSelectingMenu = true;
38306
38491
  this.openedEl = ev.target;
@@ -38349,9 +38534,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
38349
38534
  this.style.align = this.style.align || (cell === null || cell === void 0 ? void 0 : cell.defaultAlign);
38350
38535
  this.fillColor = this.style.fillColor || "#ffffff";
38351
38536
  this.textColor = this.style.textColor || "#000000";
38352
- this.menus = topbarMenuRegistry
38353
- .getAll()
38354
- .filter((item) => !item.isVisible || item.isVisible(this.env));
38537
+ this.menus = topbarMenuRegistry.getAll();
38355
38538
  }
38356
38539
  getMenuName(menu) {
38357
38540
  return getMenuName(menu, this.env);
@@ -40417,8 +40600,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40417
40600
  }
40418
40601
  const { left, right, top, bottom } = zone;
40419
40602
  const sheetId = this.getters.getActiveSheetId();
40420
- const refCol = this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1));
40421
- const refRow = this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1));
40603
+ const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
40604
+ const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
40422
40605
  if (refRow === undefined || refCol === undefined) {
40423
40606
  return 17 /* CommandResult.SelectionOutOfBound */;
40424
40607
  }
@@ -40493,10 +40676,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40493
40676
  const { col: anchorCol, row: anchorRow } = anchor.cell;
40494
40677
  return {
40495
40678
  col: this.getters.isColHidden(sheetId, anchorCol)
40496
- ? this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1)) || anchorCol
40679
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
40497
40680
  : anchorCol,
40498
40681
  row: this.getters.isRowHidden(sheetId, anchorRow)
40499
- ? this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1)) || anchorRow
40682
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
40500
40683
  : anchorRow,
40501
40684
  };
40502
40685
  }
@@ -41031,12 +41214,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
41031
41214
  else {
41032
41215
  // Shouldn't we always output the value then ?
41033
41216
  const value = cell.value;
41034
- // what if value = 0? Is this condition correct?
41035
- if (value) {
41036
- const type = getCellType(value);
41037
- attrs.push(["t", type]);
41038
- node = escapeXml /*xml*/ `<v>${value}</v>`;
41039
- }
41217
+ const type = getCellType(value);
41218
+ attrs.push(["t", type]);
41219
+ node = escapeXml /*xml*/ `<v>${value}</v>`;
41040
41220
  return { attrs, node };
41041
41221
  }
41042
41222
  }
@@ -42136,6 +42316,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42136
42316
  * Internal status of the model. Important for command handling coordination
42137
42317
  */
42138
42318
  this.status = 0 /* Status.Ready */;
42319
+ this.handlers = [];
42320
+ this.coreHandlers = [];
42139
42321
  /**
42140
42322
  * The dispatch method is the only entry point to manipulate data in the model.
42141
42323
  * This is through this method that commands are dispatched most of the time
@@ -42208,7 +42390,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42208
42390
  const command = { type, ...payload };
42209
42391
  const previousStatus = this.status;
42210
42392
  this.status = 2 /* Status.RunningCore */;
42211
- const handlers = this.isReplayingCommand ? [this.range, ...this.corePlugins] : this.handlers;
42393
+ const handlers = this.isReplayingCommand ? this.coreHandlers : this.handlers;
42212
42394
  this.dispatchToHandlers(handlers, command);
42213
42395
  this.status = previousStatus;
42214
42396
  return DispatchResult.Success;
@@ -42242,6 +42424,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42242
42424
  this.uuidGenerator.setIsFastStrategy(true);
42243
42425
  // Initiate stream processor
42244
42426
  this.selection = new SelectionStreamProcessor(this.getters);
42427
+ this.coreHandlers.push(this.range);
42428
+ this.handlers.push(this.range);
42245
42429
  // registering plugins
42246
42430
  for (let Plugin of corePluginRegistry.getAll()) {
42247
42431
  this.setupCorePlugin(Plugin, workbookData);
@@ -42251,6 +42435,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42251
42435
  this.setupUiPlugin(Plugin);
42252
42436
  }
42253
42437
  this.uuidGenerator.setIsFastStrategy(false);
42438
+ this.handlers.push(this.history);
42254
42439
  // starting plugins
42255
42440
  this.dispatch("START");
42256
42441
  // Model should be the last permanent subscriber in the list since he should render
@@ -42271,9 +42456,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42271
42456
  // by owl, since we do not rely on reactivity
42272
42457
  owl.markRaw(this);
42273
42458
  }
42274
- get handlers() {
42275
- return [this.range, ...this.corePlugins, ...this.uiPlugins, this.history];
42276
- }
42277
42459
  joinSession() {
42278
42460
  this.session.join(this.config.client);
42279
42461
  }
@@ -42292,6 +42474,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42292
42474
  this.getters[name] = plugin[name].bind(plugin);
42293
42475
  }
42294
42476
  this.uiPlugins.push(plugin);
42477
+ this.handlers.push(plugin);
42295
42478
  const layers = Plugin.layers.map((l) => [plugin, l]);
42296
42479
  this.renderers.push(...layers);
42297
42480
  this.renderers.sort((p1, p2) => p1[1] - p2[1]);
@@ -42315,6 +42498,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42315
42498
  }
42316
42499
  plugin.import(data);
42317
42500
  this.corePlugins.push(plugin);
42501
+ this.coreHandlers.push(plugin);
42502
+ this.handlers.push(plugin);
42318
42503
  }
42319
42504
  onRemoteRevisionReceived({ commands }) {
42320
42505
  for (let command of commands) {
@@ -42332,7 +42517,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42332
42517
  return;
42333
42518
  }
42334
42519
  this.isReplayingCommand = true;
42335
- this.dispatchToHandlers([this.range, ...this.corePlugins], command);
42520
+ this.dispatchToHandlers(this.coreHandlers, command);
42336
42521
  this.isReplayingCommand = false;
42337
42522
  }), this.config.transportService, revisionId);
42338
42523
  return session;
@@ -42432,7 +42617,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42432
42617
  }
42433
42618
  }
42434
42619
  data.revisionId = this.session.getRevisionId() || DEFAULT_REVISION_ID;
42435
- data = JSON.parse(JSON.stringify(data));
42620
+ data = deepCopy(data);
42436
42621
  return data;
42437
42622
  }
42438
42623
  updateMode(mode) {
@@ -42459,7 +42644,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42459
42644
  handler.exportForExcel(data);
42460
42645
  }
42461
42646
  }
42462
- data = JSON.parse(JSON.stringify(data));
42647
+ data = deepCopy(data);
42463
42648
  return getXLSX(data);
42464
42649
  }
42465
42650
  }
@@ -42593,9 +42778,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42593
42778
  Object.defineProperty(exports, '__esModule', { value: true });
42594
42779
 
42595
42780
 
42596
- __info__.version = '16.0.7';
42597
- __info__.date = '2023-04-14T12:46:24.076Z';
42598
- __info__.hash = '2b4831d';
42781
+ __info__.version = '16.0.9';
42782
+ __info__.date = '2023-04-28T12:25:41.572Z';
42783
+ __info__.hash = 'e06ca83';
42599
42784
 
42600
42785
 
42601
42786
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);