@odoo/o-spreadsheet 17.2.33 → 17.2.35

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.33
7
- * @date 2025-01-27T10:02:54.985Z
8
- * @hash 6ea43fb
6
+ * @version 17.2.35
7
+ * @date 2025-02-05T07:12:34.721Z
8
+ * @hash 76b12a1
9
9
  */
10
10
 
11
11
  'use strict';
@@ -1784,11 +1784,11 @@ const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(l
1784
1784
  * number from the point of view of the isNumber function.
1785
1785
  */
1786
1786
  function parseNumber(str, locale) {
1787
+ // remove invaluable characters
1788
+ str = str.replace(getInvaluableSymbolsRegexp(locale), "");
1787
1789
  if (locale.decimalSeparator !== ".") {
1788
1790
  str = str.replace(locale.decimalSeparator, ".");
1789
1791
  }
1790
- // remove invaluable characters
1791
- str = str.replace(getInvaluableSymbolsRegexp(locale), "");
1792
1792
  let n = Number(str);
1793
1793
  if (isNaN(n) && str.includes("%")) {
1794
1794
  n = Number(str.split("%")[0]);
@@ -17753,23 +17753,24 @@ const HLOOKUP = {
17753
17753
  description: _t("Horizontal lookup"),
17754
17754
  args: [
17755
17755
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
17756
- arg("range (range)", _t("The range to consider for the search. The first row in the range is searched for the key specified in search_key.")),
17756
+ arg("range (any, range)", _t("The range to consider for the search. The first row in the range is searched for the key specified in search_key.")),
17757
17757
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
17758
17758
  arg(`is_sorted (boolean, default=${DEFAULT_IS_SORTED})`, _t("Indicates whether the row to be searched (the first row of the specified range) is sorted, in which case the closest match for search_key will be returned.")),
17759
17759
  ],
17760
17760
  returns: ["ANY"],
17761
17761
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
17762
17762
  const _index = Math.trunc(toNumber(index?.value, this.locale));
17763
- assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
17763
+ const _range = toMatrix(range);
17764
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
17764
17765
  if (searchKey && isEvaluationError(searchKey.value)) {
17765
17766
  return searchKey;
17766
17767
  }
17767
17768
  const getValueFromRange = (range, index) => range[index][0].value;
17768
17769
  const _isSorted = toBoolean(isSorted.value);
17769
17770
  const colIndex = _isSorted
17770
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range.length, getValueFromRange)
17771
- : linearSearch(range, searchKey, "wildcard", range.length, getValueFromRange);
17772
- const col = range[colIndex];
17771
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
17772
+ : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
17773
+ const col = _range[colIndex];
17773
17774
  if (col === undefined) {
17774
17775
  return valueNotAvailable(searchKey);
17775
17776
  }
@@ -17878,36 +17879,38 @@ const LOOKUP = {
17878
17879
  description: _t("Look up a value."),
17879
17880
  args: [
17880
17881
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
17881
- arg("search_array (range)", _t("One method of using this function is to provide a single sorted row or column search_array to look through for the search_key with a second argument result_range. The other way is to combine these two arguments into one search_array where the first row or column is searched and a value is returned from the last row or column in the array. If search_key is not found, a non-exact match may be returned.")),
17882
- arg("result_range (range, optional)", _t("The range from which to return a result. The value returned corresponds to the location where search_key is found in search_range. This range must be only a single row or column and should not be used if using the search_result_array method.")),
17882
+ arg("search_array (any, range)", _t("One method of using this function is to provide a single sorted row or column search_array to look through for the search_key with a second argument result_range. The other way is to combine these two arguments into one search_array where the first row or column is searched and a value is returned from the last row or column in the array. If search_key is not found, a non-exact match may be returned.")),
17883
+ arg("result_range (any, range, optional)", _t("The range from which to return a result. The value returned corresponds to the location where search_key is found in search_range. This range must be only a single row or column and should not be used if using the search_result_array method.")),
17883
17884
  ],
17884
17885
  returns: ["ANY"],
17885
17886
  compute: function (searchKey, searchArray, resultRange) {
17886
- let nbCol = searchArray.length;
17887
- let nbRow = searchArray[0].length;
17887
+ const _searchArray = toMatrix(searchArray);
17888
+ const _resultRange = toMatrix(resultRange);
17889
+ let nbCol = _searchArray.length;
17890
+ let nbRow = _searchArray[0].length;
17888
17891
  const verticalSearch = nbRow >= nbCol;
17889
17892
  const getElement = verticalSearch
17890
17893
  ? (range, index) => range[0][index].value
17891
17894
  : (range, index) => range[index][0].value;
17892
17895
  const rangeLength = verticalSearch ? nbRow : nbCol;
17893
- const index = dichotomicSearch(searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
17896
+ const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
17894
17897
  if (index === -1 ||
17895
- (verticalSearch && searchArray[0][index] === undefined) ||
17896
- (!verticalSearch && searchArray[index][nbRow - 1] === undefined)) {
17898
+ (verticalSearch && _searchArray[0][index] === undefined) ||
17899
+ (!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
17897
17900
  return valueNotAvailable(searchKey);
17898
17901
  }
17899
- if (resultRange === undefined) {
17900
- return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
17902
+ if (_resultRange[0].length === 0) {
17903
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
17901
17904
  }
17902
- nbCol = resultRange.length;
17903
- nbRow = resultRange[0].length;
17905
+ nbCol = _resultRange.length;
17906
+ nbRow = _resultRange[0].length;
17904
17907
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
17905
17908
  if (nbCol > 1) {
17906
17909
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
17907
- return resultRange[index][0];
17910
+ return _resultRange[index][0];
17908
17911
  }
17909
17912
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
17910
- return resultRange[0][index];
17913
+ return _resultRange[0][index];
17911
17914
  },
17912
17915
  isExported: true,
17913
17916
  };
@@ -17925,28 +17928,29 @@ const MATCH = {
17925
17928
  returns: ["NUMBER"],
17926
17929
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
17927
17930
  let _searchType = toNumber(searchType, this.locale);
17928
- const nbCol = range.length;
17929
- const nbRow = range[0].length;
17931
+ const _range = toMatrix(range);
17932
+ const nbCol = _range.length;
17933
+ const nbRow = _range[0].length;
17930
17934
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
17931
17935
  let index = -1;
17932
17936
  const getElement = nbCol === 1
17933
- ? (range, index) => range[0][index].value
17934
- : (range, index) => range[index][0].value;
17935
- const rangeLen = nbCol === 1 ? range[0].length : range.length;
17937
+ ? (_range, index) => _range[0][index].value
17938
+ : (_range, index) => _range[index][0].value;
17939
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
17936
17940
  _searchType = Math.sign(_searchType);
17937
17941
  switch (_searchType) {
17938
17942
  case 1:
17939
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
17943
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
17940
17944
  break;
17941
17945
  case 0:
17942
- index = linearSearch(range, searchKey, "wildcard", rangeLen, getElement);
17946
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
17943
17947
  break;
17944
17948
  case -1:
17945
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
17949
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
17946
17950
  break;
17947
17951
  }
17948
- if ((nbCol === 1 && range[0][index] === undefined) ||
17949
- (nbCol !== 1 && range[index] === undefined)) {
17952
+ if ((nbCol === 1 && _range[0][index] === undefined) ||
17953
+ (nbCol !== 1 && _range[index] === undefined)) {
17950
17954
  return valueNotAvailable(searchKey);
17951
17955
  }
17952
17956
  return index + 1;
@@ -17997,16 +18001,17 @@ const VLOOKUP = {
17997
18001
  returns: ["ANY"],
17998
18002
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
17999
18003
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18000
- assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18004
+ const _range = toMatrix(range);
18005
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18001
18006
  if (searchKey && isEvaluationError(searchKey.value)) {
18002
18007
  return searchKey;
18003
18008
  }
18004
18009
  const getValueFromRange = (range, index) => range[0][index].value;
18005
18010
  const _isSorted = toBoolean(isSorted.value);
18006
18011
  const rowIndex = _isSorted
18007
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range[0].length, getValueFromRange)
18008
- : linearSearch(range, searchKey, "wildcard", range[0].length, getValueFromRange);
18009
- const value = range[_index - 1][rowIndex];
18012
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18013
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
18014
+ const value = _range[_index - 1][rowIndex];
18010
18015
  if (value === undefined) {
18011
18016
  return valueNotAvailable(searchKey);
18012
18017
  }
@@ -18044,30 +18049,32 @@ const XLOOKUP = {
18044
18049
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18045
18050
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18046
18051
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
18047
- assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18052
+ const _lookupRange = toMatrix(lookupRange);
18053
+ const _returnRange = toMatrix(returnRange);
18054
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18048
18055
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
18049
18056
  assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
18050
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
18057
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
18051
18058
  assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
18052
18059
  assert(() => lookupDirection === "col"
18053
- ? returnRange[0].length === lookupRange[0].length
18054
- : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18060
+ ? _returnRange[0].length === _lookupRange[0].length
18061
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18055
18062
  if (searchKey && isEvaluationError(searchKey.value)) {
18056
18063
  return [[searchKey]];
18057
18064
  }
18058
18065
  const getElement = lookupDirection === "col"
18059
18066
  ? (range, index) => range[0][index].value
18060
18067
  : (range, index) => range[index][0].value;
18061
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
18068
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
18062
18069
  const mode = MATCH_MODE[_matchMode];
18063
18070
  const reverseSearch = _searchMode === -1;
18064
18071
  const index = _searchMode === 2 || _searchMode === -2
18065
- ? dichotomicSearch(lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18066
- : linearSearch(lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18072
+ ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18073
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18067
18074
  if (index !== -1) {
18068
18075
  return lookupDirection === "col"
18069
- ? returnRange.map((col) => [col[index]])
18070
- : [returnRange[index]];
18076
+ ? _returnRange.map((col) => [col[index]])
18077
+ : [_returnRange[index]];
18071
18078
  }
18072
18079
  if (defaultValue === undefined) {
18073
18080
  return valueNotAvailable(searchKey);
@@ -34697,11 +34704,10 @@ class GridRenderer {
34697
34704
  switch (layer) {
34698
34705
  case "Background":
34699
34706
  this.drawGlobalBackground(renderingContext);
34700
- for (const zone of this.getters.getAllActiveViewportsZones()) {
34707
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
34701
34708
  const { ctx } = renderingContext;
34702
34709
  ctx.save();
34703
34710
  ctx.beginPath();
34704
- const rect = this.getters.getVisibleRect(zone);
34705
34711
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
34706
34712
  ctx.clip();
34707
34713
  const boxes = this.getGridBoxes(zone);
@@ -34971,10 +34977,8 @@ class GridRenderer {
34971
34977
  const { ctx, thinLineWidth } = renderingContext;
34972
34978
  const visibleCols = this.getters.getSheetViewVisibleCols();
34973
34979
  const left = visibleCols[0];
34974
- const right = visibleCols[visibleCols.length - 1];
34975
34980
  const visibleRows = this.getters.getSheetViewVisibleRows();
34976
34981
  const top = visibleRows[0];
34977
- const bottom = visibleRows[visibleRows.length - 1];
34978
34982
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
34979
34983
  const selection = this.getters.getSelectedZones();
34980
34984
  const selectedCols = getZonesCols(selection);
@@ -34990,7 +34994,7 @@ class GridRenderer {
34990
34994
  ctx.lineWidth = thinLineWidth;
34991
34995
  ctx.strokeStyle = "#333";
34992
34996
  // Columns headers background
34993
- for (let col = left; col <= right; col++) {
34997
+ for (const col of visibleCols) {
34994
34998
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
34995
34999
  const { x, width } = this.getters.getVisibleRect(colZone);
34996
35000
  const isColActive = activeCols.has(col);
@@ -35007,7 +35011,7 @@ class GridRenderer {
35007
35011
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
35008
35012
  }
35009
35013
  // Rows headers background
35010
- for (let row = top; row <= bottom; row++) {
35014
+ for (const row of visibleRows) {
35011
35015
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
35012
35016
  const { y, height } = this.getters.getVisibleRect(rowZone);
35013
35017
  const isRowActive = activeRows.has(row);
@@ -35033,21 +35037,21 @@ class GridRenderer {
35033
35037
  ctx.stroke();
35034
35038
  ctx.beginPath();
35035
35039
  // column text + separator
35036
- for (const i of visibleCols) {
35037
- const colSize = this.getters.getColSize(sheetId, i);
35038
- const colName = numberToLetters(i);
35039
- ctx.fillStyle = activeCols.has(i) ? "#fff" : TEXT_HEADER_COLOR;
35040
- let colStart = this.getHeaderOffset("COL", left, i);
35040
+ for (const col of visibleCols) {
35041
+ const colSize = this.getters.getColSize(sheetId, col);
35042
+ const colName = numberToLetters(col);
35043
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
35044
+ let colStart = this.getHeaderOffset("COL", left, col);
35041
35045
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
35042
35046
  ctx.moveTo(colStart + colSize, 0);
35043
35047
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
35044
35048
  }
35045
35049
  // row text + separator
35046
- for (const i of visibleRows) {
35047
- const rowSize = this.getters.getRowSize(sheetId, i);
35048
- ctx.fillStyle = activeRows.has(i) ? "#fff" : TEXT_HEADER_COLOR;
35049
- let rowStart = this.getHeaderOffset("ROW", top, i);
35050
- ctx.fillText(String(i + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
35050
+ for (const row of visibleRows) {
35051
+ const rowSize = this.getters.getRowSize(sheetId, row);
35052
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
35053
+ let rowStart = this.getHeaderOffset("ROW", top, row);
35054
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
35051
35055
  ctx.moveTo(0, rowStart + rowSize);
35052
35056
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
35053
35057
  }
@@ -35339,6 +35343,9 @@ function useGridDrawing(refName, model, canvasSize) {
35339
35343
  canvas.width = width * dpr;
35340
35344
  canvas.height = height * dpr;
35341
35345
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
35346
+ if (width === 0 || height === 0) {
35347
+ return;
35348
+ }
35342
35349
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
35343
35350
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
35344
35351
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -40896,7 +40903,7 @@ class BordersPlugin extends CorePlugin {
40896
40903
  getCommonSides(border1, border2) {
40897
40904
  const commonBorder = {};
40898
40905
  for (let side of ["top", "bottom", "left", "right"]) {
40899
- if (border1[side] && border1[side] === border2[side]) {
40906
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
40900
40907
  commonBorder[side] = border1[side];
40901
40908
  }
40902
40909
  }
@@ -51465,14 +51472,12 @@ class SheetUIPlugin extends UIPlugin {
51465
51472
  }
51466
51473
  break;
51467
51474
  case "AUTORESIZE_ROWS":
51468
- for (let row of cmd.rows) {
51469
- this.dispatch("RESIZE_COLUMNS_ROWS", {
51470
- elements: [row],
51471
- dimension: "ROW",
51472
- size: null,
51473
- sheetId: cmd.sheetId,
51474
- });
51475
- }
51475
+ this.dispatch("RESIZE_COLUMNS_ROWS", {
51476
+ elements: cmd.rows,
51477
+ dimension: "ROW",
51478
+ size: null,
51479
+ sheetId: cmd.sheetId,
51480
+ });
51476
51481
  break;
51477
51482
  }
51478
51483
  }
@@ -53809,8 +53814,17 @@ class InternalViewport {
53809
53814
  this.getters = getters;
53810
53815
  this.sheetId = sheetId;
53811
53816
  this.boundaries = boundaries;
53812
- this.viewportWidth = sizeInGrid.width;
53813
- this.viewportHeight = sizeInGrid.height;
53817
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
53818
+ throw new Error("Viewport size cannot be negative");
53819
+ }
53820
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
53821
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
53822
+ this.top = boundaries.top;
53823
+ this.bottom = boundaries.bottom;
53824
+ this.left = boundaries.left;
53825
+ this.right = boundaries.right;
53826
+ this.offsetX = offsets.x;
53827
+ this.offsetY = offsets.y;
53814
53828
  this.offsetScrollbarX = offsets.x;
53815
53829
  this.offsetScrollbarY = offsets.y;
53816
53830
  this.canScrollVertically = options.canScrollVertically;
@@ -53853,9 +53867,9 @@ class InternalViewport {
53853
53867
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
53854
53868
  );
53855
53869
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
53856
- }
53857
- if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
53858
- height += FOOTER_HEIGHT;
53870
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
53871
+ height += FOOTER_HEIGHT;
53872
+ }
53859
53873
  }
53860
53874
  return { width, height };
53861
53875
  }
@@ -53992,6 +54006,9 @@ class InternalViewport {
53992
54006
  !this.getters.isRowHidden(this.sheetId, row));
53993
54007
  }
53994
54008
  searchHeaderIndex(dimension, position, startIndex = 0) {
54009
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
54010
+ return -1;
54011
+ }
53995
54012
  const sheetId = this.sheetId;
53996
54013
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
53997
54014
  // using a binary search:
@@ -54028,7 +54045,7 @@ class InternalViewport {
54028
54045
  this.adjustViewportZoneY();
54029
54046
  }
54030
54047
  /** Corrects the viewport's horizontal offset based on the current structure
54031
- * To make sure that at least on column is visible inside the viewport.
54048
+ * To make sure that at least one column is visible inside the viewport.
54032
54049
  */
54033
54050
  adjustViewportOffsetX() {
54034
54051
  if (this.canScrollHorizontally) {
@@ -54040,7 +54057,7 @@ class InternalViewport {
54040
54057
  this.adjustViewportZoneX();
54041
54058
  }
54042
54059
  /** Corrects the viewport's vertical offset based on the current structure
54043
- * To make sure that at least on row is visible inside the viewport.
54060
+ * To make sure that at least one row is visible inside the viewport.
54044
54061
  */
54045
54062
  adjustViewportOffsetY() {
54046
54063
  if (this.canScrollVertically) {
@@ -54057,11 +54074,14 @@ class InternalViewport {
54057
54074
  const sheetId = this.sheetId;
54058
54075
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
54059
54076
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
54077
+ if (!this.viewportWidth) {
54078
+ return;
54079
+ }
54060
54080
  if (this.left === -1) {
54061
54081
  this.left = this.boundaries.left;
54062
54082
  }
54063
54083
  if (this.right === -1) {
54064
- this.right = this.getters.getNumberCols(sheetId) - 1;
54084
+ this.right = this.boundaries.right;
54065
54085
  }
54066
54086
  this.offsetX =
54067
54087
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -54073,11 +54093,14 @@ class InternalViewport {
54073
54093
  const sheetId = this.sheetId;
54074
54094
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
54075
54095
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
54096
+ if (!this.viewportHeight) {
54097
+ return;
54098
+ }
54076
54099
  if (this.top === -1) {
54077
54100
  this.top = this.boundaries.top;
54078
54101
  }
54079
54102
  if (this.bottom === -1) {
54080
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
54103
+ this.bottom = this.boundaries.bottom;
54081
54104
  }
54082
54105
  this.offsetY =
54083
54106
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -54151,7 +54174,7 @@ class SheetViewPlugin extends UIPlugin {
54151
54174
  "isPositionVisible",
54152
54175
  "getColDimensionsInViewport",
54153
54176
  "getRowDimensionsInViewport",
54154
- "getAllActiveViewportsZones",
54177
+ "getAllActiveViewportsZonesAndRect",
54155
54178
  "getRect",
54156
54179
  ];
54157
54180
  viewports = {};
@@ -54385,12 +54408,12 @@ class SheetViewPlugin extends UIPlugin {
54385
54408
  const sheetId = this.getters.getActiveSheetId();
54386
54409
  const viewports = this.getSubViewports(sheetId);
54387
54410
  //TODO ake another commit to eimprove this
54388
- return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
54411
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
54389
54412
  }
54390
54413
  getSheetViewVisibleRows() {
54391
54414
  const sheetId = this.getters.getActiveSheetId();
54392
54415
  const viewports = this.getSubViewports(sheetId);
54393
- return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
54416
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
54394
54417
  }
54395
54418
  /**
54396
54419
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -54433,19 +54456,19 @@ class SheetViewPlugin extends UIPlugin {
54433
54456
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
54434
54457
  };
54435
54458
  }
54436
- getColRowOffsetInViewport(dimension, referenceIndex, index) {
54437
- const sheetId = this.getters.getActiveSheetId();
54438
- const visibleCols = this.getters.getSheetViewVisibleCols();
54439
- const visibleRows = this.getters.getSheetViewVisibleRows();
54440
- if (index < referenceIndex) {
54441
- return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
54459
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
54460
+ if (targetHeaderIndex < referenceHeaderIndex) {
54461
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
54442
54462
  }
54463
+ const sheetId = this.getters.getActiveSheetId();
54464
+ const visibleHeaders = dimension === "COL"
54465
+ ? this.getters.getSheetViewVisibleCols()
54466
+ : this.getters.getSheetViewVisibleRows();
54467
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
54468
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
54469
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
54443
54470
  let offset = 0;
54444
- const visibleIndexes = dimension === "COL" ? visibleCols : visibleRows;
54445
- for (let i = referenceIndex; i < index; i++) {
54446
- if (!visibleIndexes.includes(i)) {
54447
- continue;
54448
- }
54471
+ for (const i of relevantIndexes) {
54449
54472
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
54450
54473
  }
54451
54474
  return offset;
@@ -54492,7 +54515,7 @@ class SheetViewPlugin extends UIPlugin {
54492
54515
  }
54493
54516
  return { canEdgeScroll, direction, delay };
54494
54517
  }
54495
- getEdgeScrollRow(y, previousY, tartingY) {
54518
+ getEdgeScrollRow(y, previousY, startingY) {
54496
54519
  let canEdgeScroll = false;
54497
54520
  let direction = 0;
54498
54521
  let delay = 0;
@@ -54513,7 +54536,7 @@ class SheetViewPlugin extends UIPlugin {
54513
54536
  delay = scrollDelay(y - height);
54514
54537
  direction = 1;
54515
54538
  }
54516
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
54539
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
54517
54540
  // 2
54518
54541
  canEdgeScroll = true;
54519
54542
  delay = scrollDelay(offsetCorrectionY - y);
@@ -54539,13 +54562,7 @@ class SheetViewPlugin extends UIPlugin {
54539
54562
  */
54540
54563
  getVisibleRectWithoutHeaders(zone) {
54541
54564
  const sheetId = this.getters.getActiveSheetId();
54542
- const viewportRects = this.getSubViewports(sheetId)
54543
- .map((viewport) => viewport.getVisibleRect(zone))
54544
- .filter(isDefined$1);
54545
- if (viewportRects.length === 0) {
54546
- return { x: 0, y: 0, width: 0, height: 0 };
54547
- }
54548
- return this.recomposeRect(viewportRects);
54565
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
54549
54566
  }
54550
54567
  /**
54551
54568
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -54553,13 +54570,7 @@ class SheetViewPlugin extends UIPlugin {
54553
54570
  */
54554
54571
  getRect(zone) {
54555
54572
  const sheetId = this.getters.getActiveSheetId();
54556
- const viewportRects = this.getSubViewports(sheetId)
54557
- .map((viewport) => viewport.getFullRect(zone))
54558
- .filter(isDefined$1);
54559
- if (viewportRects.length === 0) {
54560
- return { x: 0, y: 0, width: 0, height: 0 };
54561
- }
54562
- const rect = this.recomposeRect(viewportRects);
54573
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
54563
54574
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
54564
54575
  }
54565
54576
  /**
@@ -54604,9 +54615,18 @@ class SheetViewPlugin extends UIPlugin {
54604
54615
  end: start + (isRowHidden ? 0 : size),
54605
54616
  };
54606
54617
  }
54607
- getAllActiveViewportsZones() {
54618
+ getAllActiveViewportsZonesAndRect() {
54608
54619
  const sheetId = this.getters.getActiveSheetId();
54609
- return this.getSubViewports(sheetId);
54620
+ return this.getSubViewports(sheetId).map((viewport) => {
54621
+ return {
54622
+ zone: viewport,
54623
+ rect: {
54624
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
54625
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
54626
+ ...viewport.getMaxSize(),
54627
+ },
54628
+ };
54629
+ });
54610
54630
  }
54611
54631
  // ---------------------------------------------------------------------------
54612
54632
  // Private
@@ -54659,12 +54679,11 @@ class SheetViewPlugin extends UIPlugin {
54659
54679
  }
54660
54680
  /** gets rid of deprecated sheetIds */
54661
54681
  cleanViewports() {
54662
- const sheetIds = this.getters.getSheetIds();
54663
- for (let sheetId of Object.keys(this.viewports)) {
54664
- if (!sheetIds.includes(sheetId)) {
54665
- delete this.viewports[sheetId];
54666
- }
54682
+ const newViewport = {};
54683
+ for (const sheetId of this.getters.getSheetIds()) {
54684
+ newViewport[sheetId] = this.viewports[sheetId];
54667
54685
  }
54686
+ this.viewports = newViewport;
54668
54687
  }
54669
54688
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
54670
54689
  this.sheetViewHeight = height;
@@ -54674,14 +54693,14 @@ class SheetViewPlugin extends UIPlugin {
54674
54693
  this.recomputeViewports();
54675
54694
  }
54676
54695
  recomputeViewports() {
54677
- for (let sheetId of Object.keys(this.viewports)) {
54696
+ for (const sheetId of this.getters.getSheetIds()) {
54678
54697
  this.resetViewports(sheetId);
54679
54698
  }
54680
54699
  }
54681
54700
  setSheetViewOffset(offsetX, offsetY) {
54682
54701
  const sheetId = this.getters.getActiveSheetId();
54683
54702
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
54684
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
54703
+ this.getSubViewports(sheetId).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
54685
54704
  }
54686
54705
  getViewportOffset(sheetId) {
54687
54706
  return {
@@ -54696,8 +54715,10 @@ class SheetViewPlugin extends UIPlugin {
54696
54715
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
54697
54716
  const nCols = this.getters.getNumberCols(sheetId);
54698
54717
  const nRows = this.getters.getNumberRows(sheetId);
54699
- const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
54700
- const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
54718
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
54719
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
54720
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
54721
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
54701
54722
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
54702
54723
  const canScrollHorizontally = xRatio < 1.0;
54703
54724
  const canScrollVertically = yRatio < 1.0;
@@ -54708,14 +54729,14 @@ class SheetViewPlugin extends UIPlugin {
54708
54729
  new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: 0, bottom: ySplit - 1 }, { width: colOffset, height: rowOffset }, { canScrollHorizontally: false, canScrollVertically: false }, { x: 0, y: 0 })) ||
54709
54730
  undefined,
54710
54731
  topRight: (ySplit &&
54711
- new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width: this.sheetViewWidth - colOffset, height: rowOffset }, { canScrollHorizontally, canScrollVertically: false }, { x: canScrollHorizontally ? previousOffset.x : 0, y: 0 })) ||
54732
+ new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width: unfrozenWidth, height: rowOffset }, { canScrollHorizontally, canScrollVertically: false }, { x: canScrollHorizontally ? previousOffset.x : 0, y: 0 })) ||
54712
54733
  undefined,
54713
54734
  bottomLeft: (xSplit &&
54714
- new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height: this.sheetViewHeight - rowOffset }, { canScrollHorizontally: false, canScrollVertically }, { x: 0, y: canScrollVertically ? previousOffset.y : 0 })) ||
54735
+ new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height: unfrozenHeight }, { canScrollHorizontally: false, canScrollVertically }, { x: 0, y: canScrollVertically ? previousOffset.y : 0 })) ||
54715
54736
  undefined,
54716
54737
  bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
54717
- width: this.sheetViewWidth - colOffset,
54718
- height: this.sheetViewHeight - rowOffset,
54738
+ width: unfrozenWidth,
54739
+ height: unfrozenHeight,
54719
54740
  }, { canScrollHorizontally, canScrollVertically }, {
54720
54741
  x: canScrollHorizontally ? previousOffset.x : 0,
54721
54742
  y: canScrollVertically ? previousOffset.y : 0,
@@ -54727,7 +54748,7 @@ class SheetViewPlugin extends UIPlugin {
54727
54748
  * Adjust the viewport such that the anchor position is visible
54728
54749
  */
54729
54750
  refreshViewport(sheetId, anchorPosition) {
54730
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => {
54751
+ this.getSubViewports(sheetId).forEach((viewport) => {
54731
54752
  viewport.adjustViewportZone();
54732
54753
  viewport.adjustPosition(anchorPosition);
54733
54754
  });
@@ -54792,12 +54813,26 @@ class SheetViewPlugin extends UIPlugin {
54792
54813
  const height = this.sheetViewHeight + this.gridOffsetY;
54793
54814
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
54794
54815
  }
54795
- recomposeRect(viewportRects) {
54796
- const x = Math.min(...viewportRects.map((rect) => rect.x));
54797
- const y = Math.min(...viewportRects.map((rect) => rect.y));
54798
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
54799
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
54800
- return { x, y, width, height };
54816
+ mapViewportsToRect(sheetId, rectCallBack) {
54817
+ let x = Infinity;
54818
+ let y = Infinity;
54819
+ let width = 0;
54820
+ let height = 0;
54821
+ let hasViewports = false;
54822
+ for (const viewport of this.getSubViewports(sheetId)) {
54823
+ const rect = rectCallBack(viewport);
54824
+ if (rect) {
54825
+ hasViewports = true;
54826
+ x = Math.min(x, rect.x);
54827
+ y = Math.min(y, rect.y);
54828
+ width = Math.max(width, rect.x + rect.width);
54829
+ height = Math.max(height, rect.y + rect.height);
54830
+ }
54831
+ }
54832
+ if (!hasViewports) {
54833
+ return { x: 0, y: 0, width: 0, height: 0 };
54834
+ }
54835
+ return { x, y, width: width - x, height: height - y };
54801
54836
  }
54802
54837
  }
54803
54838
 
@@ -61136,6 +61171,6 @@ exports.tokenColors = tokenColors;
61136
61171
  exports.tokenize = tokenize;
61137
61172
 
61138
61173
 
61139
- __info__.version = "17.2.33";
61140
- __info__.date = "2025-01-27T10:02:54.985Z";
61141
- __info__.hash = "6ea43fb";
61174
+ __info__.version = "17.2.35";
61175
+ __info__.date = "2025-02-05T07:12:34.721Z";
61176
+ __info__.hash = "76b12a1";