@odoo/o-spreadsheet 16.1.7 → 16.1.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.
@@ -1020,6 +1020,10 @@
1020
1020
  }
1021
1021
  return true;
1022
1022
  }
1023
+ /** Check if the given array contains all the values of the other array. */
1024
+ function includesAll(arr, values) {
1025
+ return values.every((value) => arr.includes(value));
1026
+ }
1023
1027
  /**
1024
1028
  * Return an object with all the keys in the object that have a falsy value removed.
1025
1029
  */
@@ -1659,12 +1663,77 @@
1659
1663
  * - all digit stored in the decimal part of the number
1660
1664
  *
1661
1665
  * The 'maxDecimal' parameter allows to indicate the number of digits to not
1662
- * exceed in the decimal part, in which case digits are rounded
1666
+ * exceed in the decimal part, in which case digits are rounded.
1663
1667
  *
1664
- * Intl.Numberformat is used to properly handle all the roundings.
1665
- * e.g. 1234.7 with format ### (<> maxDecimals=0) should become 1235, not 1234
1666
1668
  **/
1667
1669
  function splitNumber(value, maxDecimals = MAX_DECIMAL_PLACES) {
1670
+ const asString = value.toString();
1671
+ if (asString.includes("e"))
1672
+ return splitNumberIntl(value, maxDecimals);
1673
+ if (Number.isInteger(value)) {
1674
+ return { integerDigits: asString, decimalDigits: undefined };
1675
+ }
1676
+ const indexOfDot = asString.indexOf(".");
1677
+ let integerDigits = asString.substring(0, indexOfDot);
1678
+ let decimalDigits = asString.substring(indexOfDot + 1);
1679
+ if (maxDecimals === 0) {
1680
+ if (Number(decimalDigits[0]) >= 5) {
1681
+ integerDigits = (Number(integerDigits) + 1).toString();
1682
+ }
1683
+ return { integerDigits, decimalDigits: undefined };
1684
+ }
1685
+ if (decimalDigits.length > maxDecimals) {
1686
+ const { integerDigits: roundedIntegerDigits, decimalDigits: roundedDecimalDigits } = limitDecimalDigits(decimalDigits, maxDecimals);
1687
+ decimalDigits = roundedDecimalDigits;
1688
+ if (roundedIntegerDigits !== "0") {
1689
+ integerDigits = (Number(integerDigits) + Number(roundedIntegerDigits)).toString();
1690
+ }
1691
+ }
1692
+ return { integerDigits, decimalDigits: removeTrailingZeroes(decimalDigits || "") };
1693
+ }
1694
+ /**
1695
+ * Return the given string minus the trailing "0" characters.
1696
+ *
1697
+ * @param numberString : a string of integers
1698
+ * @returns the numberString, minus the eventual zeroes at the end
1699
+ */
1700
+ function removeTrailingZeroes(numberString) {
1701
+ let i = numberString.length - 1;
1702
+ while (i >= 0 && numberString[i] === "0") {
1703
+ i--;
1704
+ }
1705
+ return numberString.slice(0, i + 1) || undefined;
1706
+ }
1707
+ /**
1708
+ * Limit the size of the decimal part of a number to the given number of digits.
1709
+ */
1710
+ function limitDecimalDigits(decimalDigits, maxDecimals) {
1711
+ let integerDigits = "0";
1712
+ let resultDecimalDigits = decimalDigits;
1713
+ // Note : we'd want to simply use number.toFixed() to handle the max digits & rounding,
1714
+ // but it has very strange behaviour. Ex: 12.345.toFixed(2) => "12.35", but 1.345.toFixed(2) => "1.34"
1715
+ let slicedDecimalDigits = decimalDigits.slice(0, maxDecimals);
1716
+ const i = maxDecimals;
1717
+ if (Number(Number(decimalDigits[i]) < 5)) {
1718
+ return { integerDigits, decimalDigits: slicedDecimalDigits };
1719
+ }
1720
+ // round up
1721
+ const slicedRoundedUp = (Number(slicedDecimalDigits) + 1).toString();
1722
+ if (slicedRoundedUp.length > slicedDecimalDigits.length) {
1723
+ integerDigits = (Number(integerDigits) + 1).toString();
1724
+ resultDecimalDigits = undefined;
1725
+ }
1726
+ else {
1727
+ resultDecimalDigits = slicedRoundedUp;
1728
+ }
1729
+ return { integerDigits, decimalDigits: resultDecimalDigits };
1730
+ }
1731
+ /**
1732
+ * Split numbers into decimal/integer digits using Intl.NumberFormat.
1733
+ * Supports numbers with a lot of digits that are transformed to scientific notation by
1734
+ * number.toString(), but is slow.
1735
+ */
1736
+ function splitNumberIntl(value, maxDecimals = MAX_DECIMAL_PLACES) {
1668
1737
  let formatter = numberRepresentation[maxDecimals];
1669
1738
  if (!formatter) {
1670
1739
  formatter = new Intl.NumberFormat("en-US", {
@@ -5903,13 +5972,16 @@
5903
5972
  }
5904
5973
  });
5905
5974
  }
5975
+ get visibleMenuItems() {
5976
+ return this.props.menuItems.filter((x) => x.isVisible(this.env));
5977
+ }
5906
5978
  get subMenuPosition() {
5907
5979
  const position = Object.assign({}, this.subMenu.position);
5908
5980
  position.y -= this.subMenu.scrollOffset || 0;
5909
5981
  return position;
5910
5982
  }
5911
5983
  get menuHeight() {
5912
- const menuItems = this.props.menuItems;
5984
+ const menuItems = this.visibleMenuItems;
5913
5985
  let menuItemsHeight = this.getMenuItemsHeight(menuItems);
5914
5986
  // We don't display separator at the end of a menu
5915
5987
  if (menuItems[menuItems.length - 1].separator) {
@@ -5951,7 +6023,7 @@
5951
6023
  * and the menu item at a given index.
5952
6024
  */
5953
6025
  subMenuVerticalPosition(menuIndex) {
5954
- const menusAbove = this.props.menuItems.slice(0, menuIndex);
6026
+ const menusAbove = this.visibleMenuItems.slice(0, menuIndex);
5955
6027
  return this.position.y + this.getMenuItemsHeight(menusAbove) + MENU_VERTICAL_PADDING;
5956
6028
  }
5957
6029
  onExternalClick(ev) {
@@ -6123,7 +6195,7 @@
6123
6195
  openContextMenu(position) {
6124
6196
  const registry = this.getMenuItemRegistry();
6125
6197
  this.menuState.isOpen = true;
6126
- this.menuState.menuItems = registry.getAll().filter((x) => x.isVisible(this.env));
6198
+ this.menuState.menuItems = registry.getAll();
6127
6199
  this.menuState.position = position;
6128
6200
  }
6129
6201
  get chartComponent() {
@@ -7254,6 +7326,11 @@
7254
7326
  name: REMOVE_COLUMNS_NAME,
7255
7327
  sequence: 90,
7256
7328
  action: REMOVE_COLUMNS_ACTION,
7329
+ isVisible: (env) => {
7330
+ const sheetId = env.model.getters.getActiveSheetId();
7331
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
7332
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
7333
+ },
7257
7334
  })
7258
7335
  .add("clear_column", {
7259
7336
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -7266,9 +7343,8 @@
7266
7343
  action: HIDE_COLUMNS_ACTION,
7267
7344
  isVisible: (env) => {
7268
7345
  const sheetId = env.model.getters.getActiveSheetId();
7269
- const hiddenCols = env.model.getters.getHiddenColsGroups(sheetId).flat();
7270
- return (env.model.getters.getNumberCols(sheetId) >
7271
- hiddenCols.length + env.model.getters.getElementsFromSelection("COL").length);
7346
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
7347
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
7272
7348
  },
7273
7349
  separator: true,
7274
7350
  })
@@ -7342,6 +7418,11 @@
7342
7418
  name: REMOVE_ROWS_NAME,
7343
7419
  sequence: 70,
7344
7420
  action: REMOVE_ROWS_ACTION,
7421
+ isVisible: (env) => {
7422
+ const sheetId = env.model.getters.getActiveSheetId();
7423
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
7424
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
7425
+ },
7345
7426
  })
7346
7427
  .add("clear_row", {
7347
7428
  name: DELETE_CONTENT_ROWS_NAME,
@@ -7354,9 +7435,8 @@
7354
7435
  action: HIDE_ROWS_ACTION,
7355
7436
  isVisible: (env) => {
7356
7437
  const sheetId = env.model.getters.getActiveSheetId();
7357
- const hiddenRows = env.model.getters.getHiddenRowsGroups(sheetId).flat();
7358
- return (env.model.getters.getNumberRows(sheetId) >
7359
- hiddenRows.length + env.model.getters.getElementsFromSelection("ROW").length);
7438
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
7439
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
7360
7440
  },
7361
7441
  separator: true,
7362
7442
  })
@@ -16929,14 +17009,31 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
16929
17009
  * */
16930
17010
  getCurrentSelection() {
16931
17011
  let { startElement, endElement, startSelectionOffset, endSelectionOffset } = this.getStartAndEndSelection();
16932
- let startSizeBefore = this.findSizeBeforeElement(startElement);
16933
- let endSizeBefore = this.findSizeBeforeElement(endElement);
17012
+ let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
17013
+ let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
16934
17014
  return {
16935
- start: startSizeBefore + startSelectionOffset,
16936
- end: endSizeBefore + endSelectionOffset,
17015
+ start: startSizeBefore,
17016
+ end: endSizeBefore,
16937
17017
  };
16938
17018
  }
16939
- findSizeBeforeElement(nodeToFind) {
17019
+ /**
17020
+ * Computes the text 'index' inside this.el based on the currently selected node and its offset.
17021
+ * The selected node is either a Text node or an Element node.
17022
+ *
17023
+ * case 1 -Text node:
17024
+ * the offset is the number of characters from the start of the node. We have to add this offset to the
17025
+ * content length of all previous nodes.
17026
+ *
17027
+ * case 2 - Element node:
17028
+ * the offset is the number of child nodes before the selected node. We have to add the content length of
17029
+ * all the bnodes prior to the selected node as well as the content of the child node before the offset.
17030
+ *
17031
+ * See the MDN documentation for more details.
17032
+ * https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
17033
+ * https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
17034
+ *
17035
+ */
17036
+ findSelectionIndex(nodeToFind, nodeOffset) {
16940
17037
  let it = this.iterateChildren(this.el);
16941
17038
  let usedCharacters = 0;
16942
17039
  let current = it.next();
@@ -16948,6 +17045,19 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
16948
17045
  }
16949
17046
  current = it.next();
16950
17047
  }
17048
+ if (current.value === nodeToFind) {
17049
+ if (!current.value.hasChildNodes()) {
17050
+ usedCharacters += nodeOffset;
17051
+ }
17052
+ else {
17053
+ const children = [...current.value.childNodes].slice(0, nodeOffset);
17054
+ for (const child of children) {
17055
+ if (!child.textContent)
17056
+ continue;
17057
+ usedCharacters += child.textContent.length;
17058
+ }
17059
+ }
17060
+ }
16951
17061
  return usedCharacters;
16952
17062
  }
16953
17063
  getStartAndEndSelection() {
@@ -23539,8 +23649,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23539
23649
  },
23540
23650
  "CTRL+END": () => {
23541
23651
  const sheetId = this.env.model.getters.getActiveSheetId();
23542
- const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", range(0, this.env.model.getters.getNumberCols(sheetId)).reverse());
23543
- const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", range(0, this.env.model.getters.getNumberRows(sheetId)).reverse());
23652
+ const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", this.env.model.getters.getNumberCols(sheetId) - 1, 0);
23653
+ const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", this.env.model.getters.getNumberRows(sheetId) - 1, 0);
23544
23654
  this.env.model.selection.selectCell(col, row);
23545
23655
  },
23546
23656
  "SHIFT+ ": () => {
@@ -23620,9 +23730,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23620
23730
  this.focus();
23621
23731
  }
23622
23732
  focus() {
23733
+ var _a;
23623
23734
  if (!this.env.model.getters.getSelectedFigureId() &&
23624
23735
  this.env.model.getters.getEditionMode() === "inactive") {
23625
- this.hiddenInput.el.focus();
23736
+ (_a = this.hiddenInput.el) === null || _a === void 0 ? void 0 : _a.focus();
23626
23737
  }
23627
23738
  }
23628
23739
  get gridEl() {
@@ -23823,9 +23934,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23823
23934
  }
23824
23935
  this.menuState.isOpen = true;
23825
23936
  this.menuState.position = { x, y };
23826
- this.menuState.menuItems = registries$1[type]
23827
- .getAll()
23828
- .filter((item) => !item.isVisible || item.isVisible(this.env));
23937
+ this.menuState.menuItems = registries$1[type].getAll();
23829
23938
  }
23830
23939
  copy(cut, ev) {
23831
23940
  if (!this.gridEl.contains(document.activeElement)) {
@@ -27194,7 +27303,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
27194
27303
  }
27195
27304
  }
27196
27305
  }
27197
- data = JSON.parse(JSON.stringify(data));
27306
+ data = deepCopy(data);
27198
27307
  // apply migrations, if needed
27199
27308
  if ("version" in data) {
27200
27309
  if (data.version < CURRENT_VERSION) {
@@ -29854,7 +29963,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29854
29963
  allowDispatch(cmd) {
29855
29964
  switch (cmd.type) {
29856
29965
  case "HIDE_COLUMNS_ROWS": {
29857
- if (!this.hiddenHeaders[cmd.sheetId]) {
29966
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29858
29967
  return 27 /* CommandResult.InvalidSheetId */;
29859
29968
  }
29860
29969
  const hiddenGroup = cmd.dimension === "COL"
@@ -29867,6 +29976,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29867
29976
  ? 0 /* CommandResult.Success */
29868
29977
  : 66 /* CommandResult.TooManyHiddenElements */;
29869
29978
  }
29979
+ case "REMOVE_COLUMNS_ROWS":
29980
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29981
+ return 27 /* CommandResult.InvalidSheetId */;
29982
+ }
29983
+ if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29984
+ return 8 /* CommandResult.NotEnoughElements */;
29985
+ }
29986
+ return 0 /* CommandResult.Success */;
29870
29987
  }
29871
29988
  return 0 /* CommandResult.Success */;
29872
29989
  }
@@ -29913,6 +30030,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29913
30030
  }
29914
30031
  return;
29915
30032
  }
30033
+ canRemoveHeaders(sheetId, dimension, elements) {
30034
+ const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
30035
+ return !includesAll(elements, visibleHeaders);
30036
+ }
29916
30037
  isRowHiddenByUser(sheetId, index) {
29917
30038
  return this.hiddenHeaders[sheetId].ROW[index];
29918
30039
  }
@@ -29957,6 +30078,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29957
30078
  }
29958
30079
  return consecutiveIndexes;
29959
30080
  }
30081
+ getAllVisibleHeaders(sheetId, dimension) {
30082
+ return range(0, this.hiddenHeaders[sheetId][dimension].length).filter((i) => !this.hiddenHeaders[sheetId][dimension][i]);
30083
+ }
29960
30084
  import(data) {
29961
30085
  var _a, _b;
29962
30086
  for (let sheet of data.sheets) {
@@ -30004,6 +30128,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
30004
30128
  }
30005
30129
  }
30006
30130
  HeaderVisibilityPlugin.getters = [
30131
+ "canRemoveHeaders",
30007
30132
  "getHiddenColsGroups",
30008
30133
  "getHiddenRowsGroups",
30009
30134
  "isRowHiddenByUser",
@@ -31013,14 +31138,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31013
31138
  return this.orderedSheetIds.length > 1
31014
31139
  ? 0 /* CommandResult.Success */
31015
31140
  : 9 /* CommandResult.NotEnoughSheets */;
31016
- case "REMOVE_COLUMNS_ROWS": {
31017
- const length = cmd.dimension === "COL"
31018
- ? this.getNumberCols(cmd.sheetId)
31019
- : this.getNumberRows(cmd.sheetId);
31020
- return length > cmd.elements.length
31021
- ? 0 /* CommandResult.Success */
31022
- : 8 /* CommandResult.NotEnoughElements */;
31023
- }
31024
31141
  case "FREEZE_ROWS": {
31025
31142
  return this.checkValidations(cmd, this.checkRowFreezeQuantity, this.checkRowFreezeOverlapMerge);
31026
31143
  }
@@ -31491,7 +31608,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31491
31608
  duplicateSheet(fromId, toId) {
31492
31609
  const sheet = this.getSheet(fromId);
31493
31610
  const toName = this.getDuplicateSheetName(sheet.name);
31494
- const newSheet = JSON.parse(JSON.stringify(sheet));
31611
+ const newSheet = deepCopy(sheet);
31495
31612
  newSheet.id = toId;
31496
31613
  newSheet.name = toName;
31497
31614
  for (let col = 0; col <= newSheet.numberOfCols; col++) {
@@ -31618,10 +31735,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31618
31735
  }
31619
31736
  }
31620
31737
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
31621
- for (let [index, row] of Object.entries(sheet.rows)) {
31622
- const rowIndex = parseInt(index, 10);
31738
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31739
+ const row = sheet.rows[rowIndex];
31623
31740
  for (let i in row.cells) {
31624
- const colIndex = parseInt(i, 10);
31741
+ const colIndex = Number(i);
31625
31742
  const cellId = row.cells[i];
31626
31743
  if (cellId) {
31627
31744
  if (colIndex === deletedColumn) {
@@ -31648,11 +31765,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31648
31765
  */
31649
31766
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
31650
31767
  const commands = [];
31651
- for (const [index, row] of Object.entries(sheet.rows)) {
31652
- const rowIndex = parseInt(index, 10);
31768
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31769
+ const row = sheet.rows[rowIndex];
31653
31770
  if (dimension !== "rows" || rowIndex >= addedElement) {
31654
31771
  for (let i in row.cells) {
31655
- const colIndex = parseInt(i, 10);
31772
+ const colIndex = Number(i);
31656
31773
  const cellId = row.cells[i];
31657
31774
  if (cellId) {
31658
31775
  if (dimension === "rows" || colIndex >= addedElement) {
@@ -31682,11 +31799,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31682
31799
  */
31683
31800
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
31684
31801
  const numberRows = deleteToRow - deleteFromRow + 1;
31685
- for (let [index, row] of Object.entries(sheet.rows)) {
31686
- const rowIndex = parseInt(index, 10);
31802
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31803
+ const row = sheet.rows[rowIndex];
31687
31804
  if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
31688
31805
  for (let i in row.cells) {
31689
- const colIndex = parseInt(i, 10);
31806
+ const colIndex = Number(i);
31690
31807
  const cellId = row.cells[i];
31691
31808
  if (cellId) {
31692
31809
  this.dispatch("CLEAR_CELL", {
@@ -31699,7 +31816,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31699
31816
  }
31700
31817
  if (rowIndex > deleteToRow) {
31701
31818
  for (let i in row.cells) {
31702
- const colIndex = parseInt(i, 10);
31819
+ const colIndex = Number(i);
31703
31820
  const cellId = row.cells[i];
31704
31821
  if (cellId) {
31705
31822
  this.dispatch("UPDATE_CELL_POSITION", {
@@ -31717,7 +31834,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31717
31834
  const rows = [];
31718
31835
  const cellsQueue = sheet.rows.map((row) => row.cells);
31719
31836
  for (let i in sheet.rows) {
31720
- if (parseInt(i, 10) === index) {
31837
+ if (Number(i) === index) {
31721
31838
  continue;
31722
31839
  }
31723
31840
  rows.push({
@@ -32860,13 +32977,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32860
32977
  return Boolean(id && ((_b = (_a = this.filterValues[sheetId]) === null || _a === void 0 ? void 0 : _a[id]) === null || _b === void 0 ? void 0 : _b.length));
32861
32978
  }
32862
32979
  intersectZoneWithViewport(sheetId, zone) {
32863
- const colsRange = range(zone.left, zone.right + 1);
32864
- const rowsRange = range(zone.top, zone.bottom + 1);
32865
32980
  return {
32866
- left: this.getters.findVisibleHeader(sheetId, "COL", colsRange),
32867
- right: this.getters.findVisibleHeader(sheetId, "COL", colsRange.reverse()),
32868
- top: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange),
32869
- bottom: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange.reverse()),
32981
+ left: this.getters.findVisibleHeader(sheetId, "COL", zone.left, zone.right),
32982
+ right: this.getters.findVisibleHeader(sheetId, "COL", zone.right, zone.left),
32983
+ top: this.getters.findVisibleHeader(sheetId, "ROW", zone.top, zone.bottom),
32984
+ bottom: this.getters.findVisibleHeader(sheetId, "ROW", zone.bottom, zone.top),
32870
32985
  };
32871
32986
  }
32872
32987
  updateFilter({ col, row, values, sheetId }) {
@@ -33070,48 +33185,66 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33070
33185
  this.adjustPositionY(row);
33071
33186
  }
33072
33187
  }
33073
- adjustPositionX(col) {
33188
+ adjustPositionX(targetCol) {
33074
33189
  const sheetId = this.sheetId;
33075
- const { start, end } = this.getters.getColDimensions(sheetId, col);
33076
- while (end > this.offsetX + this.offsetCorrectionX + this.viewportWidth &&
33077
- this.offsetX + this.offsetCorrectionX < start) {
33078
- this.offsetX = this.getters.getColDimensions(sheetId, this.left).end - this.offsetCorrectionX;
33079
- this.offsetScrollbarX = this.offsetX;
33080
- this.adjustViewportZoneX();
33081
- }
33082
- while (col < this.left) {
33083
- let leftCol;
33084
- for (leftCol = this.left; leftCol >= 0; leftCol--) {
33085
- if (!this.getters.isColHidden(sheetId, leftCol)) {
33190
+ const { end } = this.getters.getColDimensions(sheetId, targetCol);
33191
+ const maxCol = this.getters.getNumberCols(sheetId);
33192
+ if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
33193
+ for (let col = this.left; this.offsetX + this.offsetCorrectionX + this.viewportWidth < end; col++) {
33194
+ if (col > maxCol) {
33086
33195
  break;
33087
33196
  }
33197
+ if (this.getters.isColHidden(sheetId, col)) {
33198
+ continue;
33199
+ }
33200
+ this.offsetX = this.getters.getColDimensions(sheetId, col).end - this.offsetCorrectionX;
33201
+ this.offsetScrollbarX = this.offsetX;
33202
+ this.adjustViewportZoneX();
33203
+ }
33204
+ }
33205
+ else if (this.left > targetCol) {
33206
+ for (let col = this.left; col >= targetCol; col--) {
33207
+ if (col < 0) {
33208
+ break;
33209
+ }
33210
+ if (this.getters.isColHidden(sheetId, col)) {
33211
+ continue;
33212
+ }
33213
+ this.offsetX = this.getters.getColDimensions(sheetId, col).start - this.offsetCorrectionX;
33214
+ this.offsetScrollbarX = this.offsetX;
33215
+ this.adjustViewportZoneX();
33088
33216
  }
33089
- this.offsetX =
33090
- this.getters.getColDimensions(sheetId, leftCol - 1).start - this.offsetCorrectionX;
33091
- this.offsetScrollbarX = this.offsetX;
33092
- this.adjustViewportZoneX();
33093
33217
  }
33094
33218
  }
33095
- adjustPositionY(row) {
33219
+ adjustPositionY(targetRow) {
33096
33220
  const sheetId = this.sheetId;
33097
- while (this.getters.getRowDimensions(sheetId, row).end >
33098
- this.offsetY + this.viewportHeight + this.offsetCorrectionY &&
33099
- this.offsetY + this.offsetCorrectionY < this.getters.getRowDimensions(sheetId, row).start) {
33100
- this.offsetY = this.getters.getRowDimensions(sheetId, this.top).end - this.offsetCorrectionY;
33101
- this.offsetScrollbarY = this.offsetY;
33102
- this.adjustViewportZoneY();
33103
- }
33104
- while (row < this.top) {
33105
- let topRow;
33106
- for (topRow = this.top; topRow >= 0; topRow--) {
33107
- if (!this.getters.isRowHidden(sheetId, topRow)) {
33221
+ const { end } = this.getters.getRowDimensions(sheetId, targetRow);
33222
+ const maxRow = this.getters.getNumberRows(sheetId);
33223
+ if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
33224
+ for (let row = this.top; this.offsetY + this.viewportHeight + this.offsetCorrectionY < end; row++) {
33225
+ if (row > maxRow) {
33108
33226
  break;
33109
33227
  }
33228
+ if (this.getters.isRowHidden(sheetId, row)) {
33229
+ continue;
33230
+ }
33231
+ this.offsetY = this.getters.getRowDimensions(sheetId, row).end - this.offsetCorrectionY;
33232
+ this.offsetScrollbarY = this.offsetY;
33233
+ this.adjustViewportZoneY();
33234
+ }
33235
+ }
33236
+ else if (this.top > targetRow) {
33237
+ for (let row = this.top; row >= targetRow; row--) {
33238
+ if (row < 0) {
33239
+ break;
33240
+ }
33241
+ if (this.getters.isRowHidden(sheetId, row)) {
33242
+ continue;
33243
+ }
33244
+ this.offsetY = this.getters.getRowDimensions(sheetId, row).start - this.offsetCorrectionY;
33245
+ this.offsetScrollbarY = this.offsetY;
33246
+ this.adjustViewportZoneY();
33110
33247
  }
33111
- this.offsetY =
33112
- this.getters.getRowDimensions(sheetId, topRow - 1).start - this.offsetCorrectionY;
33113
- this.offsetScrollbarY = this.offsetY;
33114
- this.adjustViewportZoneY();
33115
33248
  }
33116
33249
  }
33117
33250
  setViewportOffset(offsetX, offsetY) {
@@ -34954,13 +35087,33 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
34954
35087
  getNextVisibleCellPosition({ sheetId, col, row }) {
34955
35088
  return {
34956
35089
  sheetId,
34957
- col: this.findVisibleHeader(sheetId, "COL", range(col, this.getters.getNumberCols(sheetId))),
34958
- row: this.findVisibleHeader(sheetId, "ROW", range(row, this.getters.getNumberRows(sheetId))),
35090
+ col: this.findVisibleHeader(sheetId, "COL", col, this.getters.getNumberCols(sheetId) - 1),
35091
+ row: this.findVisibleHeader(sheetId, "ROW", row, this.getters.getNumberRows(sheetId) - 1),
34959
35092
  };
34960
35093
  }
34961
- findVisibleHeader(sheetId, dimension, indexes) {
34962
- return indexes.find((index) => this.getters.doesHeaderExist(sheetId, dimension, index) &&
34963
- !this.isHeaderHidden(sheetId, dimension, index));
35094
+ /**
35095
+ * Find the first visible header in the range [`from` => `to`].
35096
+ *
35097
+ * Both `from` and `to` are inclusive.
35098
+ */
35099
+ findVisibleHeader(sheetId, dimension, from, to) {
35100
+ if (from <= to) {
35101
+ for (let i = from; i <= to; i++) {
35102
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
35103
+ !this.isHeaderHidden(sheetId, dimension, i)) {
35104
+ return i;
35105
+ }
35106
+ }
35107
+ }
35108
+ if (from > to) {
35109
+ for (let i = from; i >= to; i--) {
35110
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
35111
+ !this.isHeaderHidden(sheetId, dimension, i)) {
35112
+ return i;
35113
+ }
35114
+ }
35115
+ }
35116
+ return undefined;
34964
35117
  }
34965
35118
  findLastVisibleColRowIndex(sheetId, dimension, { last, first }) {
34966
35119
  const lastVisibleIndex = range(last, first, -1).find((index) => !this.isHeaderHidden(sheetId, dimension, index));
@@ -34968,7 +35121,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
34968
35121
  }
34969
35122
  findFirstVisibleColRowIndex(sheetId, dimension) {
34970
35123
  const numberOfHeaders = this.getters.getNumberHeaders(sheetId, dimension);
34971
- for (let i = 0; i < numberOfHeaders - 1; i++) {
35124
+ for (let i = 0; i < numberOfHeaders; i++) {
34972
35125
  if (dimension === "COL" && !this.isColHidden(sheetId, i)) {
34973
35126
  return i;
34974
35127
  }
@@ -39195,7 +39348,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
39195
39348
  }
39196
39349
  openContextMenu(x, y, registry, menuId) {
39197
39350
  this.menuState.isOpen = true;
39198
- this.menuState.menuItems = registry.getAll().filter((x) => x.isVisible(this.env));
39351
+ this.menuState.menuItems = registry.getAll();
39199
39352
  this.menuState.position = { x, y };
39200
39353
  this.menuState.menuId = menuId;
39201
39354
  }
@@ -40002,7 +40155,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40002
40155
  const { left, top, height } = ev.target.getBoundingClientRect();
40003
40156
  this.state.menuState.isOpen = true;
40004
40157
  this.state.menuState.position = { x: left, y: top + height };
40005
- this.state.menuState.menuItems = getMenuChildren(menu, this.env).filter((item) => !item.isVisible || item.isVisible(this.env));
40158
+ this.state.menuState.menuItems = getMenuChildren(menu, this.env);
40006
40159
  this.state.menuState.parentMenu = menu;
40007
40160
  this.isSelectingMenu = true;
40008
40161
  this.openedEl = ev.target;
@@ -40045,9 +40198,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40045
40198
  this.style.align = this.style.align || cell.defaultAlign;
40046
40199
  this.fillColor = this.style.fillColor || "#ffffff";
40047
40200
  this.textColor = this.style.textColor || "#000000";
40048
- this.menus = topbarMenuRegistry
40049
- .getAll()
40050
- .filter((item) => !item.isVisible || item.isVisible(this.env));
40201
+ this.menus = topbarMenuRegistry.getAll();
40051
40202
  }
40052
40203
  getMenuName(menu) {
40053
40204
  return getMenuName(menu, this.env);
@@ -41761,8 +41912,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
41761
41912
  }
41762
41913
  const { left, right, top, bottom } = zone;
41763
41914
  const sheetId = this.getters.getActiveSheetId();
41764
- const refCol = this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1));
41765
- const refRow = this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1));
41915
+ const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
41916
+ const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
41766
41917
  if (refRow === undefined || refCol === undefined) {
41767
41918
  return 17 /* CommandResult.SelectionOutOfBound */;
41768
41919
  }
@@ -41837,10 +41988,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
41837
41988
  const { col: anchorCol, row: anchorRow } = anchor.cell;
41838
41989
  return {
41839
41990
  col: this.getters.isColHidden(sheetId, anchorCol)
41840
- ? this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1)) || anchorCol
41991
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
41841
41992
  : anchorCol,
41842
41993
  row: this.getters.isRowHidden(sheetId, anchorRow)
41843
- ? this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1)) || anchorRow
41994
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
41844
41995
  : anchorRow,
41845
41996
  };
41846
41997
  }
@@ -43521,6 +43672,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43521
43672
  * Internal status of the model. Important for command handling coordination
43522
43673
  */
43523
43674
  this.status = 0 /* Status.Ready */;
43675
+ this.handlers = [];
43676
+ this.coreHandlers = [];
43524
43677
  /**
43525
43678
  * The dispatch method is the only entry point to manipulate data in the model.
43526
43679
  * This is through this method that commands are dispatched most of the time
@@ -43625,6 +43778,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43625
43778
  this.uuidGenerator.setIsFastStrategy(true);
43626
43779
  // Initiate stream processor
43627
43780
  this.selection = new SelectionStreamProcessor(this.getters);
43781
+ this.coreHandlers.push(this.range);
43782
+ this.handlers.push(this.range);
43628
43783
  this.corePluginConfig = this.setupCorePluginConfig();
43629
43784
  this.uiPluginConfig = this.setupUiPluginConfig();
43630
43785
  // registering plugins
@@ -43633,15 +43788,23 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43633
43788
  }
43634
43789
  Object.assign(this.getters, this.coreGetters);
43635
43790
  for (let Plugin of statefulUIPluginRegistry.getAll()) {
43636
- this.statefulUIPlugins.push(this.setupUiPlugin(Plugin));
43791
+ const plugin = this.setupUiPlugin(Plugin);
43792
+ this.statefulUIPlugins.push(plugin);
43793
+ this.handlers.push(plugin);
43637
43794
  }
43638
43795
  for (let Plugin of coreViewsPluginRegistry.getAll()) {
43639
- this.coreViewsPlugins.push(this.setupUiPlugin(Plugin));
43796
+ const plugin = this.setupUiPlugin(Plugin);
43797
+ this.coreViewsPlugins.push(plugin);
43798
+ this.handlers.push(plugin);
43799
+ this.coreHandlers.push(plugin);
43640
43800
  }
43641
43801
  for (let Plugin of featurePluginRegistry.getAll()) {
43642
- this.featurePlugins.push(this.setupUiPlugin(Plugin));
43802
+ const plugin = this.setupUiPlugin(Plugin);
43803
+ this.featurePlugins.push(plugin);
43804
+ this.handlers.push(plugin);
43643
43805
  }
43644
43806
  this.uuidGenerator.setIsFastStrategy(false);
43807
+ this.handlers.push(this.history);
43645
43808
  // starting plugins
43646
43809
  this.dispatch("START");
43647
43810
  // Model should be the last permanent subscriber in the list since he should render
@@ -43663,12 +43826,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43663
43826
  // by owl, since we do not rely on reactivity
43664
43827
  owl.markRaw(this);
43665
43828
  }
43666
- get handlers() {
43667
- return [this.range, ...this.corePlugins, ...this.allUIPlugins, this.history];
43668
- }
43669
- get allUIPlugins() {
43670
- return [...this.statefulUIPlugins, ...this.coreViewsPlugins, ...this.featurePlugins];
43671
- }
43672
43829
  joinSession() {
43673
43830
  this.session.join(this.config.client);
43674
43831
  }
@@ -43710,6 +43867,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43710
43867
  }
43711
43868
  plugin.import(data);
43712
43869
  this.corePlugins.push(plugin);
43870
+ this.coreHandlers.push(plugin);
43871
+ this.handlers.push(plugin);
43713
43872
  }
43714
43873
  onRemoteRevisionReceived({ commands }) {
43715
43874
  for (let command of commands) {
@@ -43852,7 +44011,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43852
44011
  }
43853
44012
  }
43854
44013
  data.revisionId = this.session.getRevisionId() || DEFAULT_REVISION_ID;
43855
- data = JSON.parse(JSON.stringify(data));
44014
+ data = deepCopy(data);
43856
44015
  return data;
43857
44016
  }
43858
44017
  updateMode(mode) {
@@ -43880,7 +44039,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43880
44039
  handler.exportForExcel(data);
43881
44040
  }
43882
44041
  }
43883
- data = JSON.parse(JSON.stringify(data));
44042
+ data = deepCopy(data);
43884
44043
  return getXLSX(data);
43885
44044
  }
43886
44045
  garbageCollectExternalResources() {
@@ -44023,9 +44182,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
44023
44182
  Object.defineProperty(exports, '__esModule', { value: true });
44024
44183
 
44025
44184
 
44026
- __info__.version = '16.1.7';
44027
- __info__.date = '2023-04-13T08:29:52.140Z';
44028
- __info__.hash = '3141a6d';
44185
+ __info__.version = '16.1.9';
44186
+ __info__.date = '2023-04-21T07:29:41.080Z';
44187
+ __info__.hash = '686bffa';
44029
44188
 
44030
44189
 
44031
44190
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);