@odoo/o-spreadsheet 16.0.6 → 16.0.8

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", {
@@ -3971,13 +4040,16 @@
3971
4040
  }
3972
4041
  });
3973
4042
  }
4043
+ get visibleMenuItems() {
4044
+ return this.props.menuItems.filter((x) => x.isVisible(this.env));
4045
+ }
3974
4046
  get subMenuPosition() {
3975
4047
  const position = Object.assign({}, this.subMenu.position);
3976
4048
  position.y -= this.subMenu.scrollOffset || 0;
3977
4049
  return position;
3978
4050
  }
3979
4051
  get menuHeight() {
3980
- return this.menuComponentHeight(this.props.menuItems);
4052
+ return this.menuComponentHeight(this.visibleMenuItems);
3981
4053
  }
3982
4054
  get subMenuHeight() {
3983
4055
  return this.menuComponentHeight(this.subMenu.menuItems);
@@ -4013,7 +4085,7 @@
4013
4085
  * and the menu item at a given index.
4014
4086
  */
4015
4087
  subMenuVerticalPosition(position) {
4016
- const menusAbove = this.props.menuItems.slice(0, position);
4088
+ const menusAbove = this.visibleMenuItems.slice(0, position);
4017
4089
  return this.menuComponentHeight(menusAbove) + this.position.y;
4018
4090
  }
4019
4091
  onExternalClick(ev) {
@@ -5546,6 +5618,11 @@
5546
5618
  name: REMOVE_COLUMNS_NAME,
5547
5619
  sequence: 90,
5548
5620
  action: REMOVE_COLUMNS_ACTION,
5621
+ isVisible: (env) => {
5622
+ const sheetId = env.model.getters.getActiveSheetId();
5623
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
5624
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
5625
+ },
5549
5626
  })
5550
5627
  .add("clear_column", {
5551
5628
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -5558,9 +5635,8 @@
5558
5635
  action: HIDE_COLUMNS_ACTION,
5559
5636
  isVisible: (env) => {
5560
5637
  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);
5638
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
5639
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
5564
5640
  },
5565
5641
  separator: true,
5566
5642
  })
@@ -5634,6 +5710,11 @@
5634
5710
  name: REMOVE_ROWS_NAME,
5635
5711
  sequence: 70,
5636
5712
  action: REMOVE_ROWS_ACTION,
5713
+ isVisible: (env) => {
5714
+ const sheetId = env.model.getters.getActiveSheetId();
5715
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
5716
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
5717
+ },
5637
5718
  })
5638
5719
  .add("clear_row", {
5639
5720
  name: DELETE_CONTENT_ROWS_NAME,
@@ -5646,9 +5727,8 @@
5646
5727
  action: HIDE_ROWS_ACTION,
5647
5728
  isVisible: (env) => {
5648
5729
  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);
5730
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
5731
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
5652
5732
  },
5653
5733
  separator: true,
5654
5734
  })
@@ -10310,7 +10390,7 @@
10310
10390
  openContextMenu(position) {
10311
10391
  const registry = this.getMenuItemRegistry();
10312
10392
  this.menuState.isOpen = true;
10313
- this.menuState.menuItems = registry.getAll().filter((x) => x.isVisible(this.env));
10393
+ this.menuState.menuItems = registry.getAll();
10314
10394
  this.menuState.position = position;
10315
10395
  }
10316
10396
  get chartComponent() {
@@ -19830,14 +19910,31 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19830
19910
  * */
19831
19911
  getCurrentSelection() {
19832
19912
  let { startElement, endElement, startSelectionOffset, endSelectionOffset } = this.getStartAndEndSelection();
19833
- let startSizeBefore = this.findSizeBeforeElement(startElement);
19834
- let endSizeBefore = this.findSizeBeforeElement(endElement);
19913
+ let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
19914
+ let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
19835
19915
  return {
19836
- start: startSizeBefore + startSelectionOffset,
19837
- end: endSizeBefore + endSelectionOffset,
19916
+ start: startSizeBefore,
19917
+ end: endSizeBefore,
19838
19918
  };
19839
19919
  }
19840
- findSizeBeforeElement(nodeToFind) {
19920
+ /**
19921
+ * Computes the text 'index' inside this.el based on the currently selected node and its offset.
19922
+ * The selected node is either a Text node or an Element node.
19923
+ *
19924
+ * case 1 -Text node:
19925
+ * the offset is the number of characters from the start of the node. We have to add this offset to the
19926
+ * content length of all previous nodes.
19927
+ *
19928
+ * case 2 - Element node:
19929
+ * the offset is the number of child nodes before the selected node. We have to add the content length of
19930
+ * all the bnodes prior to the selected node as well as the content of the child node before the offset.
19931
+ *
19932
+ * See the MDN documentation for more details.
19933
+ * https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
19934
+ * https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
19935
+ *
19936
+ */
19937
+ findSelectionIndex(nodeToFind, nodeOffset) {
19841
19938
  let it = this.iterateChildren(this.el);
19842
19939
  let usedCharacters = 0;
19843
19940
  let current = it.next();
@@ -19849,6 +19946,19 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19849
19946
  }
19850
19947
  current = it.next();
19851
19948
  }
19949
+ if (current.value === nodeToFind) {
19950
+ if (!current.value.hasChildNodes()) {
19951
+ usedCharacters += nodeOffset;
19952
+ }
19953
+ else {
19954
+ const children = [...current.value.childNodes].slice(0, nodeOffset);
19955
+ for (const child of children) {
19956
+ if (!child.textContent)
19957
+ continue;
19958
+ usedCharacters += child.textContent.length;
19959
+ }
19960
+ }
19961
+ }
19852
19962
  return usedCharacters;
19853
19963
  }
19854
19964
  getStartAndEndSelection() {
@@ -22334,8 +22444,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22334
22444
  },
22335
22445
  "CTRL+END": () => {
22336
22446
  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());
22447
+ const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", this.env.model.getters.getNumberCols(sheetId) - 1, 0);
22448
+ const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", this.env.model.getters.getNumberRows(sheetId) - 1, 0);
22339
22449
  this.env.model.selection.selectCell(col, row);
22340
22450
  },
22341
22451
  "SHIFT+ ": () => {
@@ -22411,9 +22521,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22411
22521
  this.focus();
22412
22522
  }
22413
22523
  focus() {
22524
+ var _a;
22414
22525
  if (!this.env.model.getters.getSelectedFigureId() &&
22415
22526
  this.env.model.getters.getEditionMode() === "inactive") {
22416
- this.hiddenInput.el.focus();
22527
+ (_a = this.hiddenInput.el) === null || _a === void 0 ? void 0 : _a.focus();
22417
22528
  }
22418
22529
  }
22419
22530
  get gridEl() {
@@ -22617,9 +22728,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22617
22728
  this.closeOpenedPopover();
22618
22729
  this.menuState.isOpen = true;
22619
22730
  this.menuState.position = { x, y };
22620
- this.menuState.menuItems = registries$1[type]
22621
- .getAll()
22622
- .filter((item) => !item.isVisible || item.isVisible(this.env));
22731
+ this.menuState.menuItems = registries$1[type].getAll();
22623
22732
  }
22624
22733
  copy(cut, ev) {
22625
22734
  if (!this.gridEl.contains(document.activeElement)) {
@@ -26357,7 +26466,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
26357
26466
  }
26358
26467
  }
26359
26468
  }
26360
- data = JSON.parse(JSON.stringify(data));
26469
+ data = deepCopy(data);
26361
26470
  // apply migrations, if needed
26362
26471
  if ("version" in data) {
26363
26472
  if (data.version < CURRENT_VERSION) {
@@ -28942,7 +29051,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28942
29051
  allowDispatch(cmd) {
28943
29052
  switch (cmd.type) {
28944
29053
  case "HIDE_COLUMNS_ROWS": {
28945
- if (!this.hiddenHeaders[cmd.sheetId]) {
29054
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
28946
29055
  return 27 /* CommandResult.InvalidSheetId */;
28947
29056
  }
28948
29057
  const hiddenGroup = cmd.dimension === "COL"
@@ -28955,6 +29064,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28955
29064
  ? 0 /* CommandResult.Success */
28956
29065
  : 65 /* CommandResult.TooManyHiddenElements */;
28957
29066
  }
29067
+ case "REMOVE_COLUMNS_ROWS":
29068
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29069
+ return 27 /* CommandResult.InvalidSheetId */;
29070
+ }
29071
+ if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29072
+ return 8 /* CommandResult.NotEnoughElements */;
29073
+ }
29074
+ return 0 /* CommandResult.Success */;
28958
29075
  }
28959
29076
  return 0 /* CommandResult.Success */;
28960
29077
  }
@@ -29001,6 +29118,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29001
29118
  }
29002
29119
  return;
29003
29120
  }
29121
+ canRemoveHeaders(sheetId, dimension, elements) {
29122
+ const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
29123
+ return !includesAll(elements, visibleHeaders);
29124
+ }
29004
29125
  isRowHiddenByUser(sheetId, index) {
29005
29126
  return this.hiddenHeaders[sheetId].ROW[index];
29006
29127
  }
@@ -29045,6 +29166,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29045
29166
  }
29046
29167
  return consecutiveIndexes;
29047
29168
  }
29169
+ getAllVisibleHeaders(sheetId, dimension) {
29170
+ return range(0, this.hiddenHeaders[sheetId][dimension].length).filter((i) => !this.hiddenHeaders[sheetId][dimension][i]);
29171
+ }
29048
29172
  import(data) {
29049
29173
  var _a, _b;
29050
29174
  for (let sheet of data.sheets) {
@@ -29092,6 +29216,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29092
29216
  }
29093
29217
  }
29094
29218
  HeaderVisibilityPlugin.getters = [
29219
+ "canRemoveHeaders",
29095
29220
  "getHiddenColsGroups",
29096
29221
  "getHiddenRowsGroups",
29097
29222
  "isRowHiddenByUser",
@@ -29592,14 +29717,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29592
29717
  return this.orderedSheetIds.length > 1
29593
29718
  ? 0 /* CommandResult.Success */
29594
29719
  : 9 /* CommandResult.NotEnoughSheets */;
29595
- case "REMOVE_COLUMNS_ROWS": {
29596
- const length = cmd.dimension === "COL"
29597
- ? this.getNumberCols(cmd.sheetId)
29598
- : this.getNumberRows(cmd.sheetId);
29599
- return length > cmd.elements.length
29600
- ? 0 /* CommandResult.Success */
29601
- : 8 /* CommandResult.NotEnoughElements */;
29602
- }
29603
29720
  case "FREEZE_ROWS": {
29604
29721
  return this.checkValidations(cmd, this.checkRowFreezeQuantity, this.checkRowFreezeOverlapMerge);
29605
29722
  }
@@ -30083,7 +30200,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30083
30200
  duplicateSheet(fromId, toId) {
30084
30201
  const sheet = this.getSheet(fromId);
30085
30202
  const toName = this.getDuplicateSheetName(sheet.name);
30086
- const newSheet = JSON.parse(JSON.stringify(sheet));
30203
+ const newSheet = deepCopy(sheet);
30087
30204
  newSheet.id = toId;
30088
30205
  newSheet.name = toName;
30089
30206
  for (let col = 0; col <= newSheet.numberOfCols; col++) {
@@ -30210,10 +30327,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30210
30327
  }
30211
30328
  }
30212
30329
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
30213
- for (let [index, row] of Object.entries(sheet.rows)) {
30214
- const rowIndex = parseInt(index, 10);
30330
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
30331
+ const row = sheet.rows[rowIndex];
30215
30332
  for (let i in row.cells) {
30216
- const colIndex = parseInt(i, 10);
30333
+ const colIndex = Number(i);
30217
30334
  const cellId = row.cells[i];
30218
30335
  if (cellId) {
30219
30336
  if (colIndex === deletedColumn) {
@@ -30240,11 +30357,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30240
30357
  */
30241
30358
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
30242
30359
  const commands = [];
30243
- for (const [index, row] of Object.entries(sheet.rows)) {
30244
- const rowIndex = parseInt(index, 10);
30360
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
30361
+ const row = sheet.rows[rowIndex];
30245
30362
  if (dimension !== "rows" || rowIndex >= addedElement) {
30246
30363
  for (let i in row.cells) {
30247
- const colIndex = parseInt(i, 10);
30364
+ const colIndex = Number(i);
30248
30365
  const cellId = row.cells[i];
30249
30366
  if (cellId) {
30250
30367
  if (dimension === "rows" || colIndex >= addedElement) {
@@ -30274,11 +30391,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30274
30391
  */
30275
30392
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
30276
30393
  const numberRows = deleteToRow - deleteFromRow + 1;
30277
- for (let [index, row] of Object.entries(sheet.rows)) {
30278
- const rowIndex = parseInt(index, 10);
30394
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
30395
+ const row = sheet.rows[rowIndex];
30279
30396
  if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
30280
30397
  for (let i in row.cells) {
30281
- const colIndex = parseInt(i, 10);
30398
+ const colIndex = Number(i);
30282
30399
  const cellId = row.cells[i];
30283
30400
  if (cellId) {
30284
30401
  this.dispatch("CLEAR_CELL", {
@@ -30291,7 +30408,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30291
30408
  }
30292
30409
  if (rowIndex > deleteToRow) {
30293
30410
  for (let i in row.cells) {
30294
- const colIndex = parseInt(i, 10);
30411
+ const colIndex = Number(i);
30295
30412
  const cellId = row.cells[i];
30296
30413
  if (cellId) {
30297
30414
  this.dispatch("UPDATE_CELL_POSITION", {
@@ -30309,7 +30426,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30309
30426
  const rows = [];
30310
30427
  const cellsQueue = sheet.rows.map((row) => row.cells);
30311
30428
  for (let i in sheet.rows) {
30312
- if (parseInt(i, 10) === index) {
30429
+ if (Number(i) === index) {
30313
30430
  continue;
30314
30431
  }
30315
30432
  rows.push({
@@ -32945,13 +33062,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32945
33062
  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
33063
  }
32947
33064
  intersectZoneWithViewport(sheetId, zone) {
32948
- const colsRange = range(zone.left, zone.right + 1);
32949
- const rowsRange = range(zone.top, zone.bottom + 1);
32950
33065
  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()),
33066
+ left: this.getters.findVisibleHeader(sheetId, "COL", zone.left, zone.right),
33067
+ right: this.getters.findVisibleHeader(sheetId, "COL", zone.right, zone.left),
33068
+ top: this.getters.findVisibleHeader(sheetId, "ROW", zone.top, zone.bottom),
33069
+ bottom: this.getters.findVisibleHeader(sheetId, "ROW", zone.bottom, zone.top),
32955
33070
  };
32956
33071
  }
32957
33072
  updateFilter({ col, row, values, sheetId }) {
@@ -33393,13 +33508,33 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33393
33508
  }
33394
33509
  getNextVisibleCellPosition(sheetId, col, row) {
33395
33510
  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))),
33511
+ col: this.findVisibleHeader(sheetId, "COL", col, this.getters.getNumberCols(sheetId) - 1),
33512
+ row: this.findVisibleHeader(sheetId, "ROW", row, this.getters.getNumberRows(sheetId) - 1),
33398
33513
  };
33399
33514
  }
33400
- findVisibleHeader(sheetId, dimension, indexes) {
33401
- return indexes.find((index) => this.getters.doesHeaderExist(sheetId, dimension, index) &&
33402
- !this.isHeaderHidden(sheetId, dimension, index));
33515
+ /**
33516
+ * Find the first visible header in the range [`from` => `to`].
33517
+ *
33518
+ * Both `from` and `to` are inclusive.
33519
+ */
33520
+ findVisibleHeader(sheetId, dimension, from, to) {
33521
+ if (from <= to) {
33522
+ for (let i = from; i <= to; i++) {
33523
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
33524
+ !this.isHeaderHidden(sheetId, dimension, i)) {
33525
+ return i;
33526
+ }
33527
+ }
33528
+ }
33529
+ if (from > to) {
33530
+ for (let i = from; i >= to; i--) {
33531
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
33532
+ !this.isHeaderHidden(sheetId, dimension, i)) {
33533
+ return i;
33534
+ }
33535
+ }
33536
+ }
33537
+ return undefined;
33403
33538
  }
33404
33539
  findLastVisibleColRowIndex(sheetId, dimension, indexes) {
33405
33540
  let lastIndex;
@@ -33412,7 +33547,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33412
33547
  }
33413
33548
  findFirstVisibleColRowIndex(sheetId, dimension) {
33414
33549
  const numberOfHeaders = this.getters.getNumberHeaders(sheetId, dimension);
33415
- for (let i = 0; i < numberOfHeaders - 1; i++) {
33550
+ for (let i = 0; i < numberOfHeaders; i++) {
33416
33551
  if (dimension === "COL" && !this.isColHidden(sheetId, i)) {
33417
33552
  return i;
33418
33553
  }
@@ -35986,48 +36121,66 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
35986
36121
  this.adjustPositionY(row);
35987
36122
  }
35988
36123
  }
35989
- adjustPositionX(col) {
36124
+ adjustPositionX(targetCol) {
35990
36125
  const sheetId = this.sheetId;
35991
- const { start, end } = this.getters.getColDimensions(sheetId, col);
35992
- while (end > this.offsetX + this.offsetCorrectionX + this.viewportWidth &&
35993
- this.offsetX + this.offsetCorrectionX < start) {
35994
- this.offsetX = this.getters.getColDimensions(sheetId, this.left).end - this.offsetCorrectionX;
35995
- this.offsetScrollbarX = this.offsetX;
35996
- this.adjustViewportZoneX();
35997
- }
35998
- while (col < this.left) {
35999
- let leftCol;
36000
- for (leftCol = this.left; leftCol >= 0; leftCol--) {
36001
- if (!this.getters.isColHidden(sheetId, leftCol)) {
36126
+ const { end } = this.getters.getColDimensions(sheetId, targetCol);
36127
+ const maxCol = this.getters.getNumberCols(sheetId);
36128
+ if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
36129
+ for (let col = this.left; this.offsetX + this.offsetCorrectionX + this.viewportWidth < end; col++) {
36130
+ if (col > maxCol) {
36131
+ break;
36132
+ }
36133
+ if (this.getters.isColHidden(sheetId, col)) {
36134
+ continue;
36135
+ }
36136
+ this.offsetX = this.getters.getColDimensions(sheetId, col).end - this.offsetCorrectionX;
36137
+ this.offsetScrollbarX = this.offsetX;
36138
+ this.adjustViewportZoneX();
36139
+ }
36140
+ }
36141
+ else if (this.left > targetCol) {
36142
+ for (let col = this.left; col >= targetCol; col--) {
36143
+ if (col < 0) {
36002
36144
  break;
36003
36145
  }
36146
+ if (this.getters.isColHidden(sheetId, col)) {
36147
+ continue;
36148
+ }
36149
+ this.offsetX = this.getters.getColDimensions(sheetId, col).start - this.offsetCorrectionX;
36150
+ this.offsetScrollbarX = this.offsetX;
36151
+ this.adjustViewportZoneX();
36004
36152
  }
36005
- this.offsetX =
36006
- this.getters.getColDimensions(sheetId, leftCol - 1).start - this.offsetCorrectionX;
36007
- this.offsetScrollbarX = this.offsetX;
36008
- this.adjustViewportZoneX();
36009
36153
  }
36010
36154
  }
36011
- adjustPositionY(row) {
36155
+ adjustPositionY(targetRow) {
36012
36156
  const sheetId = this.sheetId;
36013
- while (this.getters.getRowDimensions(sheetId, row).end >
36014
- this.offsetY + this.viewportHeight + this.offsetCorrectionY &&
36015
- this.offsetY + this.offsetCorrectionY < this.getters.getRowDimensions(sheetId, row).start) {
36016
- this.offsetY = this.getters.getRowDimensions(sheetId, this.top).end - this.offsetCorrectionY;
36017
- this.offsetScrollbarY = this.offsetY;
36018
- this.adjustViewportZoneY();
36019
- }
36020
- while (row < this.top) {
36021
- let topRow;
36022
- for (topRow = this.top; topRow >= 0; topRow--) {
36023
- if (!this.getters.isRowHidden(sheetId, topRow)) {
36157
+ const { end } = this.getters.getRowDimensions(sheetId, targetRow);
36158
+ const maxRow = this.getters.getNumberRows(sheetId);
36159
+ if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
36160
+ for (let row = this.top; this.offsetY + this.viewportHeight + this.offsetCorrectionY < end; row++) {
36161
+ if (row > maxRow) {
36162
+ break;
36163
+ }
36164
+ if (this.getters.isRowHidden(sheetId, row)) {
36165
+ continue;
36166
+ }
36167
+ this.offsetY = this.getters.getRowDimensions(sheetId, row).end - this.offsetCorrectionY;
36168
+ this.offsetScrollbarY = this.offsetY;
36169
+ this.adjustViewportZoneY();
36170
+ }
36171
+ }
36172
+ else if (this.top > targetRow) {
36173
+ for (let row = this.top; row >= targetRow; row--) {
36174
+ if (row < 0) {
36024
36175
  break;
36025
36176
  }
36177
+ if (this.getters.isRowHidden(sheetId, row)) {
36178
+ continue;
36179
+ }
36180
+ this.offsetY = this.getters.getRowDimensions(sheetId, row).start - this.offsetCorrectionY;
36181
+ this.offsetScrollbarY = this.offsetY;
36182
+ this.adjustViewportZoneY();
36026
36183
  }
36027
- this.offsetY =
36028
- this.getters.getRowDimensions(sheetId, topRow - 1).start - this.offsetCorrectionY;
36029
- this.offsetScrollbarY = this.offsetY;
36030
- this.adjustViewportZoneY();
36031
36184
  }
36032
36185
  }
36033
36186
  setViewportOffset(offsetX, offsetY) {
@@ -37521,7 +37674,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
37521
37674
  }
37522
37675
  openContextMenu(x, y, registry, menuId) {
37523
37676
  this.menuState.isOpen = true;
37524
- this.menuState.menuItems = registry.getAll().filter((x) => x.isVisible(this.env));
37677
+ this.menuState.menuItems = registry.getAll();
37525
37678
  this.menuState.position = { x, y };
37526
37679
  this.menuState.menuId = menuId;
37527
37680
  }
@@ -38282,7 +38435,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
38282
38435
  const { left, top, height } = ev.target.getBoundingClientRect();
38283
38436
  this.state.menuState.isOpen = true;
38284
38437
  this.state.menuState.position = { x: left, y: top + height };
38285
- this.state.menuState.menuItems = getMenuChildren(menu, this.env).filter((item) => !item.isVisible || item.isVisible(this.env));
38438
+ this.state.menuState.menuItems = getMenuChildren(menu, this.env);
38286
38439
  this.state.menuState.parentMenu = menu;
38287
38440
  this.isSelectingMenu = true;
38288
38441
  this.openedEl = ev.target;
@@ -38331,9 +38484,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
38331
38484
  this.style.align = this.style.align || (cell === null || cell === void 0 ? void 0 : cell.defaultAlign);
38332
38485
  this.fillColor = this.style.fillColor || "#ffffff";
38333
38486
  this.textColor = this.style.textColor || "#000000";
38334
- this.menus = topbarMenuRegistry
38335
- .getAll()
38336
- .filter((item) => !item.isVisible || item.isVisible(this.env));
38487
+ this.menus = topbarMenuRegistry.getAll();
38337
38488
  }
38338
38489
  getMenuName(menu) {
38339
38490
  return getMenuName(menu, this.env);
@@ -40399,8 +40550,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40399
40550
  }
40400
40551
  const { left, right, top, bottom } = zone;
40401
40552
  const sheetId = this.getters.getActiveSheetId();
40402
- const refCol = this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1));
40403
- const refRow = this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1));
40553
+ const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
40554
+ const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
40404
40555
  if (refRow === undefined || refCol === undefined) {
40405
40556
  return 17 /* CommandResult.SelectionOutOfBound */;
40406
40557
  }
@@ -40475,10 +40626,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40475
40626
  const { col: anchorCol, row: anchorRow } = anchor.cell;
40476
40627
  return {
40477
40628
  col: this.getters.isColHidden(sheetId, anchorCol)
40478
- ? this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1)) || anchorCol
40629
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
40479
40630
  : anchorCol,
40480
40631
  row: this.getters.isRowHidden(sheetId, anchorRow)
40481
- ? this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1)) || anchorRow
40632
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
40482
40633
  : anchorRow,
40483
40634
  };
40484
40635
  }
@@ -42118,6 +42269,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42118
42269
  * Internal status of the model. Important for command handling coordination
42119
42270
  */
42120
42271
  this.status = 0 /* Status.Ready */;
42272
+ this.handlers = [];
42273
+ this.coreHandlers = [];
42121
42274
  /**
42122
42275
  * The dispatch method is the only entry point to manipulate data in the model.
42123
42276
  * This is through this method that commands are dispatched most of the time
@@ -42190,7 +42343,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42190
42343
  const command = { type, ...payload };
42191
42344
  const previousStatus = this.status;
42192
42345
  this.status = 2 /* Status.RunningCore */;
42193
- const handlers = this.isReplayingCommand ? [this.range, ...this.corePlugins] : this.handlers;
42346
+ const handlers = this.isReplayingCommand ? this.coreHandlers : this.handlers;
42194
42347
  this.dispatchToHandlers(handlers, command);
42195
42348
  this.status = previousStatus;
42196
42349
  return DispatchResult.Success;
@@ -42224,6 +42377,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42224
42377
  this.uuidGenerator.setIsFastStrategy(true);
42225
42378
  // Initiate stream processor
42226
42379
  this.selection = new SelectionStreamProcessor(this.getters);
42380
+ this.coreHandlers.push(this.range);
42381
+ this.handlers.push(this.range);
42227
42382
  // registering plugins
42228
42383
  for (let Plugin of corePluginRegistry.getAll()) {
42229
42384
  this.setupCorePlugin(Plugin, workbookData);
@@ -42233,6 +42388,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42233
42388
  this.setupUiPlugin(Plugin);
42234
42389
  }
42235
42390
  this.uuidGenerator.setIsFastStrategy(false);
42391
+ this.handlers.push(this.history);
42236
42392
  // starting plugins
42237
42393
  this.dispatch("START");
42238
42394
  // Model should be the last permanent subscriber in the list since he should render
@@ -42253,9 +42409,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42253
42409
  // by owl, since we do not rely on reactivity
42254
42410
  owl.markRaw(this);
42255
42411
  }
42256
- get handlers() {
42257
- return [this.range, ...this.corePlugins, ...this.uiPlugins, this.history];
42258
- }
42259
42412
  joinSession() {
42260
42413
  this.session.join(this.config.client);
42261
42414
  }
@@ -42274,6 +42427,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42274
42427
  this.getters[name] = plugin[name].bind(plugin);
42275
42428
  }
42276
42429
  this.uiPlugins.push(plugin);
42430
+ this.handlers.push(plugin);
42277
42431
  const layers = Plugin.layers.map((l) => [plugin, l]);
42278
42432
  this.renderers.push(...layers);
42279
42433
  this.renderers.sort((p1, p2) => p1[1] - p2[1]);
@@ -42297,6 +42451,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42297
42451
  }
42298
42452
  plugin.import(data);
42299
42453
  this.corePlugins.push(plugin);
42454
+ this.coreHandlers.push(plugin);
42455
+ this.handlers.push(plugin);
42300
42456
  }
42301
42457
  onRemoteRevisionReceived({ commands }) {
42302
42458
  for (let command of commands) {
@@ -42314,7 +42470,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42314
42470
  return;
42315
42471
  }
42316
42472
  this.isReplayingCommand = true;
42317
- this.dispatchToHandlers([this.range, ...this.corePlugins], command);
42473
+ this.dispatchToHandlers(this.coreHandlers, command);
42318
42474
  this.isReplayingCommand = false;
42319
42475
  }), this.config.transportService, revisionId);
42320
42476
  return session;
@@ -42414,7 +42570,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42414
42570
  }
42415
42571
  }
42416
42572
  data.revisionId = this.session.getRevisionId() || DEFAULT_REVISION_ID;
42417
- data = JSON.parse(JSON.stringify(data));
42573
+ data = deepCopy(data);
42418
42574
  return data;
42419
42575
  }
42420
42576
  updateMode(mode) {
@@ -42441,7 +42597,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42441
42597
  handler.exportForExcel(data);
42442
42598
  }
42443
42599
  }
42444
- data = JSON.parse(JSON.stringify(data));
42600
+ data = deepCopy(data);
42445
42601
  return getXLSX(data);
42446
42602
  }
42447
42603
  }
@@ -42575,9 +42731,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42575
42731
  Object.defineProperty(exports, '__esModule', { value: true });
42576
42732
 
42577
42733
 
42578
- __info__.version = '16.0.6';
42579
- __info__.date = '2023-04-13T08:30:26.954Z';
42580
- __info__.hash = '8d60b5c';
42734
+ __info__.version = '16.0.8';
42735
+ __info__.date = '2023-04-21T07:29:33.894Z';
42736
+ __info__.hash = 'dbd7aa4';
42581
42737
 
42582
42738
 
42583
42739
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);