@odoo/o-spreadsheet 17.2.34 → 17.2.36

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.34
7
- * @date 2025-01-31T07:58:03.953Z
8
- * @hash 0bffee9
6
+ * @version 17.2.36
7
+ * @date 2025-02-10T08:59:25.719Z
8
+ * @hash 5a942bd
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -605,9 +605,16 @@
605
605
  }
606
606
  return true;
607
607
  }
608
- /** Check if the given array contains all the values of the other array. */
608
+ /**
609
+ * Check if the given array contains all the values of the other array.
610
+ * It makes the assumption that both array do not contain duplicates.
611
+ */
609
612
  function includesAll(arr, values) {
610
- return values.every((value) => arr.includes(value));
613
+ if (arr.length < values.length) {
614
+ return false;
615
+ }
616
+ const set = new Set(arr);
617
+ return values.every((value) => set.has(value));
611
618
  }
612
619
  /**
613
620
  * Return an object with all the keys in the object that have a falsy value removed.
@@ -17752,23 +17759,24 @@ stores.inject(MyMetaStore, storeInstance);
17752
17759
  description: _t("Horizontal lookup"),
17753
17760
  args: [
17754
17761
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
17755
- 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.")),
17762
+ 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.")),
17756
17763
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
17757
17764
  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.")),
17758
17765
  ],
17759
17766
  returns: ["ANY"],
17760
17767
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
17761
17768
  const _index = Math.trunc(toNumber(index?.value, this.locale));
17762
- assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
17769
+ const _range = toMatrix(range);
17770
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
17763
17771
  if (searchKey && isEvaluationError(searchKey.value)) {
17764
17772
  return searchKey;
17765
17773
  }
17766
17774
  const getValueFromRange = (range, index) => range[index][0].value;
17767
17775
  const _isSorted = toBoolean(isSorted.value);
17768
17776
  const colIndex = _isSorted
17769
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range.length, getValueFromRange)
17770
- : linearSearch(range, searchKey, "wildcard", range.length, getValueFromRange);
17771
- const col = range[colIndex];
17777
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
17778
+ : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
17779
+ const col = _range[colIndex];
17772
17780
  if (col === undefined) {
17773
17781
  return valueNotAvailable(searchKey);
17774
17782
  }
@@ -17877,36 +17885,38 @@ stores.inject(MyMetaStore, storeInstance);
17877
17885
  description: _t("Look up a value."),
17878
17886
  args: [
17879
17887
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
17880
- 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.")),
17881
- 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.")),
17888
+ 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.")),
17889
+ 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.")),
17882
17890
  ],
17883
17891
  returns: ["ANY"],
17884
17892
  compute: function (searchKey, searchArray, resultRange) {
17885
- let nbCol = searchArray.length;
17886
- let nbRow = searchArray[0].length;
17893
+ const _searchArray = toMatrix(searchArray);
17894
+ const _resultRange = toMatrix(resultRange);
17895
+ let nbCol = _searchArray.length;
17896
+ let nbRow = _searchArray[0].length;
17887
17897
  const verticalSearch = nbRow >= nbCol;
17888
17898
  const getElement = verticalSearch
17889
17899
  ? (range, index) => range[0][index].value
17890
17900
  : (range, index) => range[index][0].value;
17891
17901
  const rangeLength = verticalSearch ? nbRow : nbCol;
17892
- const index = dichotomicSearch(searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
17902
+ const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
17893
17903
  if (index === -1 ||
17894
- (verticalSearch && searchArray[0][index] === undefined) ||
17895
- (!verticalSearch && searchArray[index][nbRow - 1] === undefined)) {
17904
+ (verticalSearch && _searchArray[0][index] === undefined) ||
17905
+ (!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
17896
17906
  return valueNotAvailable(searchKey);
17897
17907
  }
17898
- if (resultRange === undefined) {
17899
- return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
17908
+ if (_resultRange[0].length === 0) {
17909
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
17900
17910
  }
17901
- nbCol = resultRange.length;
17902
- nbRow = resultRange[0].length;
17911
+ nbCol = _resultRange.length;
17912
+ nbRow = _resultRange[0].length;
17903
17913
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
17904
17914
  if (nbCol > 1) {
17905
17915
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
17906
- return resultRange[index][0];
17916
+ return _resultRange[index][0];
17907
17917
  }
17908
17918
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
17909
- return resultRange[0][index];
17919
+ return _resultRange[0][index];
17910
17920
  },
17911
17921
  isExported: true,
17912
17922
  };
@@ -17924,28 +17934,29 @@ stores.inject(MyMetaStore, storeInstance);
17924
17934
  returns: ["NUMBER"],
17925
17935
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
17926
17936
  let _searchType = toNumber(searchType, this.locale);
17927
- const nbCol = range.length;
17928
- const nbRow = range[0].length;
17937
+ const _range = toMatrix(range);
17938
+ const nbCol = _range.length;
17939
+ const nbRow = _range[0].length;
17929
17940
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
17930
17941
  let index = -1;
17931
17942
  const getElement = nbCol === 1
17932
- ? (range, index) => range[0][index].value
17933
- : (range, index) => range[index][0].value;
17934
- const rangeLen = nbCol === 1 ? range[0].length : range.length;
17943
+ ? (_range, index) => _range[0][index].value
17944
+ : (_range, index) => _range[index][0].value;
17945
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
17935
17946
  _searchType = Math.sign(_searchType);
17936
17947
  switch (_searchType) {
17937
17948
  case 1:
17938
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
17949
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
17939
17950
  break;
17940
17951
  case 0:
17941
- index = linearSearch(range, searchKey, "wildcard", rangeLen, getElement);
17952
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
17942
17953
  break;
17943
17954
  case -1:
17944
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
17955
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
17945
17956
  break;
17946
17957
  }
17947
- if ((nbCol === 1 && range[0][index] === undefined) ||
17948
- (nbCol !== 1 && range[index] === undefined)) {
17958
+ if ((nbCol === 1 && _range[0][index] === undefined) ||
17959
+ (nbCol !== 1 && _range[index] === undefined)) {
17949
17960
  return valueNotAvailable(searchKey);
17950
17961
  }
17951
17962
  return index + 1;
@@ -17996,16 +18007,17 @@ stores.inject(MyMetaStore, storeInstance);
17996
18007
  returns: ["ANY"],
17997
18008
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
17998
18009
  const _index = Math.trunc(toNumber(index?.value, this.locale));
17999
- assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18010
+ const _range = toMatrix(range);
18011
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18000
18012
  if (searchKey && isEvaluationError(searchKey.value)) {
18001
18013
  return searchKey;
18002
18014
  }
18003
18015
  const getValueFromRange = (range, index) => range[0][index].value;
18004
18016
  const _isSorted = toBoolean(isSorted.value);
18005
18017
  const rowIndex = _isSorted
18006
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range[0].length, getValueFromRange)
18007
- : linearSearch(range, searchKey, "wildcard", range[0].length, getValueFromRange);
18008
- const value = range[_index - 1][rowIndex];
18018
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18019
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
18020
+ const value = _range[_index - 1][rowIndex];
18009
18021
  if (value === undefined) {
18010
18022
  return valueNotAvailable(searchKey);
18011
18023
  }
@@ -18043,30 +18055,32 @@ stores.inject(MyMetaStore, storeInstance);
18043
18055
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18044
18056
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18045
18057
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
18046
- assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18058
+ const _lookupRange = toMatrix(lookupRange);
18059
+ const _returnRange = toMatrix(returnRange);
18060
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18047
18061
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
18048
18062
  assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
18049
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
18063
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
18050
18064
  assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
18051
18065
  assert(() => lookupDirection === "col"
18052
- ? returnRange[0].length === lookupRange[0].length
18053
- : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18066
+ ? _returnRange[0].length === _lookupRange[0].length
18067
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18054
18068
  if (searchKey && isEvaluationError(searchKey.value)) {
18055
18069
  return [[searchKey]];
18056
18070
  }
18057
18071
  const getElement = lookupDirection === "col"
18058
18072
  ? (range, index) => range[0][index].value
18059
18073
  : (range, index) => range[index][0].value;
18060
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
18074
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
18061
18075
  const mode = MATCH_MODE[_matchMode];
18062
18076
  const reverseSearch = _searchMode === -1;
18063
18077
  const index = _searchMode === 2 || _searchMode === -2
18064
- ? dichotomicSearch(lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18065
- : linearSearch(lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18078
+ ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18079
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18066
18080
  if (index !== -1) {
18067
18081
  return lookupDirection === "col"
18068
- ? returnRange.map((col) => [col[index]])
18069
- : [returnRange[index]];
18082
+ ? _returnRange.map((col) => [col[index]])
18083
+ : [_returnRange[index]];
18070
18084
  }
18071
18085
  if (defaultValue === undefined) {
18072
18086
  return valueNotAvailable(searchKey);
@@ -34696,11 +34710,10 @@ stores.inject(MyMetaStore, storeInstance);
34696
34710
  switch (layer) {
34697
34711
  case "Background":
34698
34712
  this.drawGlobalBackground(renderingContext);
34699
- for (const zone of this.getters.getAllActiveViewportsZones()) {
34713
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
34700
34714
  const { ctx } = renderingContext;
34701
34715
  ctx.save();
34702
34716
  ctx.beginPath();
34703
- const rect = this.getters.getVisibleRect(zone);
34704
34717
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
34705
34718
  ctx.clip();
34706
34719
  const boxes = this.getGridBoxes(zone);
@@ -34970,10 +34983,8 @@ stores.inject(MyMetaStore, storeInstance);
34970
34983
  const { ctx, thinLineWidth } = renderingContext;
34971
34984
  const visibleCols = this.getters.getSheetViewVisibleCols();
34972
34985
  const left = visibleCols[0];
34973
- const right = visibleCols[visibleCols.length - 1];
34974
34986
  const visibleRows = this.getters.getSheetViewVisibleRows();
34975
34987
  const top = visibleRows[0];
34976
- const bottom = visibleRows[visibleRows.length - 1];
34977
34988
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
34978
34989
  const selection = this.getters.getSelectedZones();
34979
34990
  const selectedCols = getZonesCols(selection);
@@ -34989,7 +35000,7 @@ stores.inject(MyMetaStore, storeInstance);
34989
35000
  ctx.lineWidth = thinLineWidth;
34990
35001
  ctx.strokeStyle = "#333";
34991
35002
  // Columns headers background
34992
- for (let col = left; col <= right; col++) {
35003
+ for (const col of visibleCols) {
34993
35004
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
34994
35005
  const { x, width } = this.getters.getVisibleRect(colZone);
34995
35006
  const isColActive = activeCols.has(col);
@@ -35006,7 +35017,7 @@ stores.inject(MyMetaStore, storeInstance);
35006
35017
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
35007
35018
  }
35008
35019
  // Rows headers background
35009
- for (let row = top; row <= bottom; row++) {
35020
+ for (const row of visibleRows) {
35010
35021
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
35011
35022
  const { y, height } = this.getters.getVisibleRect(rowZone);
35012
35023
  const isRowActive = activeRows.has(row);
@@ -35032,21 +35043,21 @@ stores.inject(MyMetaStore, storeInstance);
35032
35043
  ctx.stroke();
35033
35044
  ctx.beginPath();
35034
35045
  // column text + separator
35035
- for (const i of visibleCols) {
35036
- const colSize = this.getters.getColSize(sheetId, i);
35037
- const colName = numberToLetters(i);
35038
- ctx.fillStyle = activeCols.has(i) ? "#fff" : TEXT_HEADER_COLOR;
35039
- let colStart = this.getHeaderOffset("COL", left, i);
35046
+ for (const col of visibleCols) {
35047
+ const colSize = this.getters.getColSize(sheetId, col);
35048
+ const colName = numberToLetters(col);
35049
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
35050
+ let colStart = this.getHeaderOffset("COL", left, col);
35040
35051
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
35041
35052
  ctx.moveTo(colStart + colSize, 0);
35042
35053
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
35043
35054
  }
35044
35055
  // row text + separator
35045
- for (const i of visibleRows) {
35046
- const rowSize = this.getters.getRowSize(sheetId, i);
35047
- ctx.fillStyle = activeRows.has(i) ? "#fff" : TEXT_HEADER_COLOR;
35048
- let rowStart = this.getHeaderOffset("ROW", top, i);
35049
- ctx.fillText(String(i + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
35056
+ for (const row of visibleRows) {
35057
+ const rowSize = this.getters.getRowSize(sheetId, row);
35058
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
35059
+ let rowStart = this.getHeaderOffset("ROW", top, row);
35060
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
35050
35061
  ctx.moveTo(0, rowStart + rowSize);
35051
35062
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
35052
35063
  }
@@ -35338,6 +35349,9 @@ stores.inject(MyMetaStore, storeInstance);
35338
35349
  canvas.width = width * dpr;
35339
35350
  canvas.height = height * dpr;
35340
35351
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
35352
+ if (width === 0 || height === 0) {
35353
+ return;
35354
+ }
35341
35355
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
35342
35356
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
35343
35357
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -40895,7 +40909,7 @@ stores.inject(MyMetaStore, storeInstance);
40895
40909
  getCommonSides(border1, border2) {
40896
40910
  const commonBorder = {};
40897
40911
  for (let side of ["top", "bottom", "left", "right"]) {
40898
- if (border1[side] && border1[side] === border2[side]) {
40912
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
40899
40913
  commonBorder[side] = border1[side];
40900
40914
  }
40901
40915
  }
@@ -53806,8 +53820,17 @@ stores.inject(MyMetaStore, storeInstance);
53806
53820
  this.getters = getters;
53807
53821
  this.sheetId = sheetId;
53808
53822
  this.boundaries = boundaries;
53809
- this.viewportWidth = sizeInGrid.width;
53810
- this.viewportHeight = sizeInGrid.height;
53823
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
53824
+ throw new Error("Viewport size cannot be negative");
53825
+ }
53826
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
53827
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
53828
+ this.top = boundaries.top;
53829
+ this.bottom = boundaries.bottom;
53830
+ this.left = boundaries.left;
53831
+ this.right = boundaries.right;
53832
+ this.offsetX = offsets.x;
53833
+ this.offsetY = offsets.y;
53811
53834
  this.offsetScrollbarX = offsets.x;
53812
53835
  this.offsetScrollbarY = offsets.y;
53813
53836
  this.canScrollVertically = options.canScrollVertically;
@@ -53850,9 +53873,9 @@ stores.inject(MyMetaStore, storeInstance);
53850
53873
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
53851
53874
  );
53852
53875
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
53853
- }
53854
- if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
53855
- height += FOOTER_HEIGHT;
53876
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
53877
+ height += FOOTER_HEIGHT;
53878
+ }
53856
53879
  }
53857
53880
  return { width, height };
53858
53881
  }
@@ -53989,6 +54012,9 @@ stores.inject(MyMetaStore, storeInstance);
53989
54012
  !this.getters.isRowHidden(this.sheetId, row));
53990
54013
  }
53991
54014
  searchHeaderIndex(dimension, position, startIndex = 0) {
54015
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
54016
+ return -1;
54017
+ }
53992
54018
  const sheetId = this.sheetId;
53993
54019
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
53994
54020
  // using a binary search:
@@ -54025,7 +54051,7 @@ stores.inject(MyMetaStore, storeInstance);
54025
54051
  this.adjustViewportZoneY();
54026
54052
  }
54027
54053
  /** Corrects the viewport's horizontal offset based on the current structure
54028
- * To make sure that at least on column is visible inside the viewport.
54054
+ * To make sure that at least one column is visible inside the viewport.
54029
54055
  */
54030
54056
  adjustViewportOffsetX() {
54031
54057
  if (this.canScrollHorizontally) {
@@ -54037,7 +54063,7 @@ stores.inject(MyMetaStore, storeInstance);
54037
54063
  this.adjustViewportZoneX();
54038
54064
  }
54039
54065
  /** Corrects the viewport's vertical offset based on the current structure
54040
- * To make sure that at least on row is visible inside the viewport.
54066
+ * To make sure that at least one row is visible inside the viewport.
54041
54067
  */
54042
54068
  adjustViewportOffsetY() {
54043
54069
  if (this.canScrollVertically) {
@@ -54054,11 +54080,14 @@ stores.inject(MyMetaStore, storeInstance);
54054
54080
  const sheetId = this.sheetId;
54055
54081
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
54056
54082
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
54083
+ if (!this.viewportWidth) {
54084
+ return;
54085
+ }
54057
54086
  if (this.left === -1) {
54058
54087
  this.left = this.boundaries.left;
54059
54088
  }
54060
54089
  if (this.right === -1) {
54061
- this.right = this.getters.getNumberCols(sheetId) - 1;
54090
+ this.right = this.boundaries.right;
54062
54091
  }
54063
54092
  this.offsetX =
54064
54093
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -54070,11 +54099,14 @@ stores.inject(MyMetaStore, storeInstance);
54070
54099
  const sheetId = this.sheetId;
54071
54100
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
54072
54101
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
54102
+ if (!this.viewportHeight) {
54103
+ return;
54104
+ }
54073
54105
  if (this.top === -1) {
54074
54106
  this.top = this.boundaries.top;
54075
54107
  }
54076
54108
  if (this.bottom === -1) {
54077
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
54109
+ this.bottom = this.boundaries.bottom;
54078
54110
  }
54079
54111
  this.offsetY =
54080
54112
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -54148,7 +54180,7 @@ stores.inject(MyMetaStore, storeInstance);
54148
54180
  "isPositionVisible",
54149
54181
  "getColDimensionsInViewport",
54150
54182
  "getRowDimensionsInViewport",
54151
- "getAllActiveViewportsZones",
54183
+ "getAllActiveViewportsZonesAndRect",
54152
54184
  "getRect",
54153
54185
  ];
54154
54186
  viewports = {};
@@ -54382,12 +54414,12 @@ stores.inject(MyMetaStore, storeInstance);
54382
54414
  const sheetId = this.getters.getActiveSheetId();
54383
54415
  const viewports = this.getSubViewports(sheetId);
54384
54416
  //TODO ake another commit to eimprove this
54385
- return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
54417
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
54386
54418
  }
54387
54419
  getSheetViewVisibleRows() {
54388
54420
  const sheetId = this.getters.getActiveSheetId();
54389
54421
  const viewports = this.getSubViewports(sheetId);
54390
- return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
54422
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
54391
54423
  }
54392
54424
  /**
54393
54425
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -54430,19 +54462,19 @@ stores.inject(MyMetaStore, storeInstance);
54430
54462
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
54431
54463
  };
54432
54464
  }
54433
- getColRowOffsetInViewport(dimension, referenceIndex, index) {
54434
- const sheetId = this.getters.getActiveSheetId();
54435
- const visibleCols = this.getters.getSheetViewVisibleCols();
54436
- const visibleRows = this.getters.getSheetViewVisibleRows();
54437
- if (index < referenceIndex) {
54438
- return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
54465
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
54466
+ if (targetHeaderIndex < referenceHeaderIndex) {
54467
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
54439
54468
  }
54469
+ const sheetId = this.getters.getActiveSheetId();
54470
+ const visibleHeaders = dimension === "COL"
54471
+ ? this.getters.getSheetViewVisibleCols()
54472
+ : this.getters.getSheetViewVisibleRows();
54473
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
54474
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
54475
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
54440
54476
  let offset = 0;
54441
- const visibleIndexes = dimension === "COL" ? visibleCols : visibleRows;
54442
- for (let i = referenceIndex; i < index; i++) {
54443
- if (!visibleIndexes.includes(i)) {
54444
- continue;
54445
- }
54477
+ for (const i of relevantIndexes) {
54446
54478
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
54447
54479
  }
54448
54480
  return offset;
@@ -54489,7 +54521,7 @@ stores.inject(MyMetaStore, storeInstance);
54489
54521
  }
54490
54522
  return { canEdgeScroll, direction, delay };
54491
54523
  }
54492
- getEdgeScrollRow(y, previousY, tartingY) {
54524
+ getEdgeScrollRow(y, previousY, startingY) {
54493
54525
  let canEdgeScroll = false;
54494
54526
  let direction = 0;
54495
54527
  let delay = 0;
@@ -54510,7 +54542,7 @@ stores.inject(MyMetaStore, storeInstance);
54510
54542
  delay = scrollDelay(y - height);
54511
54543
  direction = 1;
54512
54544
  }
54513
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
54545
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
54514
54546
  // 2
54515
54547
  canEdgeScroll = true;
54516
54548
  delay = scrollDelay(offsetCorrectionY - y);
@@ -54536,13 +54568,7 @@ stores.inject(MyMetaStore, storeInstance);
54536
54568
  */
54537
54569
  getVisibleRectWithoutHeaders(zone) {
54538
54570
  const sheetId = this.getters.getActiveSheetId();
54539
- const viewportRects = this.getSubViewports(sheetId)
54540
- .map((viewport) => viewport.getVisibleRect(zone))
54541
- .filter(isDefined$1);
54542
- if (viewportRects.length === 0) {
54543
- return { x: 0, y: 0, width: 0, height: 0 };
54544
- }
54545
- return this.recomposeRect(viewportRects);
54571
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
54546
54572
  }
54547
54573
  /**
54548
54574
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -54550,13 +54576,7 @@ stores.inject(MyMetaStore, storeInstance);
54550
54576
  */
54551
54577
  getRect(zone) {
54552
54578
  const sheetId = this.getters.getActiveSheetId();
54553
- const viewportRects = this.getSubViewports(sheetId)
54554
- .map((viewport) => viewport.getFullRect(zone))
54555
- .filter(isDefined$1);
54556
- if (viewportRects.length === 0) {
54557
- return { x: 0, y: 0, width: 0, height: 0 };
54558
- }
54559
- const rect = this.recomposeRect(viewportRects);
54579
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
54560
54580
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
54561
54581
  }
54562
54582
  /**
@@ -54601,9 +54621,18 @@ stores.inject(MyMetaStore, storeInstance);
54601
54621
  end: start + (isRowHidden ? 0 : size),
54602
54622
  };
54603
54623
  }
54604
- getAllActiveViewportsZones() {
54624
+ getAllActiveViewportsZonesAndRect() {
54605
54625
  const sheetId = this.getters.getActiveSheetId();
54606
- return this.getSubViewports(sheetId);
54626
+ return this.getSubViewports(sheetId).map((viewport) => {
54627
+ return {
54628
+ zone: viewport,
54629
+ rect: {
54630
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
54631
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
54632
+ ...viewport.getMaxSize(),
54633
+ },
54634
+ };
54635
+ });
54607
54636
  }
54608
54637
  // ---------------------------------------------------------------------------
54609
54638
  // Private
@@ -54656,12 +54685,11 @@ stores.inject(MyMetaStore, storeInstance);
54656
54685
  }
54657
54686
  /** gets rid of deprecated sheetIds */
54658
54687
  cleanViewports() {
54659
- const sheetIds = this.getters.getSheetIds();
54660
- for (let sheetId of Object.keys(this.viewports)) {
54661
- if (!sheetIds.includes(sheetId)) {
54662
- delete this.viewports[sheetId];
54663
- }
54688
+ const newViewport = {};
54689
+ for (const sheetId of this.getters.getSheetIds()) {
54690
+ newViewport[sheetId] = this.viewports[sheetId];
54664
54691
  }
54692
+ this.viewports = newViewport;
54665
54693
  }
54666
54694
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
54667
54695
  this.sheetViewHeight = height;
@@ -54671,14 +54699,14 @@ stores.inject(MyMetaStore, storeInstance);
54671
54699
  this.recomputeViewports();
54672
54700
  }
54673
54701
  recomputeViewports() {
54674
- for (let sheetId of Object.keys(this.viewports)) {
54702
+ for (const sheetId of this.getters.getSheetIds()) {
54675
54703
  this.resetViewports(sheetId);
54676
54704
  }
54677
54705
  }
54678
54706
  setSheetViewOffset(offsetX, offsetY) {
54679
54707
  const sheetId = this.getters.getActiveSheetId();
54680
54708
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
54681
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
54709
+ this.getSubViewports(sheetId).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
54682
54710
  }
54683
54711
  getViewportOffset(sheetId) {
54684
54712
  return {
@@ -54693,8 +54721,10 @@ stores.inject(MyMetaStore, storeInstance);
54693
54721
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
54694
54722
  const nCols = this.getters.getNumberCols(sheetId);
54695
54723
  const nRows = this.getters.getNumberRows(sheetId);
54696
- const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
54697
- const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
54724
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
54725
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
54726
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
54727
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
54698
54728
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
54699
54729
  const canScrollHorizontally = xRatio < 1.0;
54700
54730
  const canScrollVertically = yRatio < 1.0;
@@ -54705,14 +54735,14 @@ stores.inject(MyMetaStore, storeInstance);
54705
54735
  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 })) ||
54706
54736
  undefined,
54707
54737
  topRight: (ySplit &&
54708
- 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 })) ||
54738
+ 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 })) ||
54709
54739
  undefined,
54710
54740
  bottomLeft: (xSplit &&
54711
- 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 })) ||
54741
+ 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 })) ||
54712
54742
  undefined,
54713
54743
  bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
54714
- width: this.sheetViewWidth - colOffset,
54715
- height: this.sheetViewHeight - rowOffset,
54744
+ width: unfrozenWidth,
54745
+ height: unfrozenHeight,
54716
54746
  }, { canScrollHorizontally, canScrollVertically }, {
54717
54747
  x: canScrollHorizontally ? previousOffset.x : 0,
54718
54748
  y: canScrollVertically ? previousOffset.y : 0,
@@ -54724,7 +54754,7 @@ stores.inject(MyMetaStore, storeInstance);
54724
54754
  * Adjust the viewport such that the anchor position is visible
54725
54755
  */
54726
54756
  refreshViewport(sheetId, anchorPosition) {
54727
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => {
54757
+ this.getSubViewports(sheetId).forEach((viewport) => {
54728
54758
  viewport.adjustViewportZone();
54729
54759
  viewport.adjustPosition(anchorPosition);
54730
54760
  });
@@ -54789,12 +54819,26 @@ stores.inject(MyMetaStore, storeInstance);
54789
54819
  const height = this.sheetViewHeight + this.gridOffsetY;
54790
54820
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
54791
54821
  }
54792
- recomposeRect(viewportRects) {
54793
- const x = Math.min(...viewportRects.map((rect) => rect.x));
54794
- const y = Math.min(...viewportRects.map((rect) => rect.y));
54795
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
54796
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
54797
- return { x, y, width, height };
54822
+ mapViewportsToRect(sheetId, rectCallBack) {
54823
+ let x = Infinity;
54824
+ let y = Infinity;
54825
+ let width = 0;
54826
+ let height = 0;
54827
+ let hasViewports = false;
54828
+ for (const viewport of this.getSubViewports(sheetId)) {
54829
+ const rect = rectCallBack(viewport);
54830
+ if (rect) {
54831
+ hasViewports = true;
54832
+ x = Math.min(x, rect.x);
54833
+ y = Math.min(y, rect.y);
54834
+ width = Math.max(width, rect.x + rect.width);
54835
+ height = Math.max(height, rect.y + rect.height);
54836
+ }
54837
+ }
54838
+ if (!hasViewports) {
54839
+ return { x: 0, y: 0, width: 0, height: 0 };
54840
+ }
54841
+ return { x, y, width: width - x, height: height - y };
54798
54842
  }
54799
54843
  }
54800
54844
 
@@ -61133,9 +61177,9 @@ stores.inject(MyMetaStore, storeInstance);
61133
61177
  exports.tokenize = tokenize;
61134
61178
 
61135
61179
 
61136
- __info__.version = "17.2.34";
61137
- __info__.date = "2025-01-31T07:58:03.953Z";
61138
- __info__.hash = "0bffee9";
61180
+ __info__.version = "17.2.36";
61181
+ __info__.date = "2025-02-10T08:59:25.719Z";
61182
+ __info__.hash = "5a942bd";
61139
61183
 
61140
61184
 
61141
61185
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);