@odoo/o-spreadsheet 17.4.20 → 17.4.21

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 17.4.20
6
- * @date 2025-01-31T08:00:07.103Z
7
- * @hash 54a344a
5
+ * @version 17.4.21
6
+ * @date 2025-02-05T06:46:54.366Z
7
+ * @hash 0c55e18
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -18882,22 +18882,23 @@ stores.inject(MyMetaStore, storeInstance);
18882
18882
  description: _t("Horizontal lookup"),
18883
18883
  args: [
18884
18884
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18885
- 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.")),
18885
+ 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.")),
18886
18886
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18887
18887
  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.")),
18888
18888
  ],
18889
18889
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18890
18890
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18891
- assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18891
+ const _range = toMatrix(range);
18892
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18892
18893
  if (searchKey && isEvaluationError(searchKey.value)) {
18893
18894
  return searchKey;
18894
18895
  }
18895
18896
  const getValueFromRange = (range, index) => range[index][0].value;
18896
18897
  const _isSorted = toBoolean(isSorted.value);
18897
18898
  const colIndex = _isSorted
18898
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range.length, getValueFromRange)
18899
- : linearSearch(range, searchKey, "wildcard", range.length, getValueFromRange);
18900
- const col = range[colIndex];
18899
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
18900
+ : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
18901
+ const col = _range[colIndex];
18901
18902
  if (col === undefined) {
18902
18903
  return valueNotAvailable(searchKey);
18903
18904
  }
@@ -18996,35 +18997,37 @@ stores.inject(MyMetaStore, storeInstance);
18996
18997
  description: _t("Look up a value."),
18997
18998
  args: [
18998
18999
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18999
- 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.")),
19000
- 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.")),
19000
+ 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.")),
19001
+ 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.")),
19001
19002
  ],
19002
19003
  compute: function (searchKey, searchArray, resultRange) {
19003
- let nbCol = searchArray.length;
19004
- let nbRow = searchArray[0].length;
19004
+ const _searchArray = toMatrix(searchArray);
19005
+ const _resultRange = toMatrix(resultRange);
19006
+ let nbCol = _searchArray.length;
19007
+ let nbRow = _searchArray[0].length;
19005
19008
  const verticalSearch = nbRow >= nbCol;
19006
19009
  const getElement = verticalSearch
19007
19010
  ? (range, index) => range[0][index].value
19008
19011
  : (range, index) => range[index][0].value;
19009
19012
  const rangeLength = verticalSearch ? nbRow : nbCol;
19010
- const index = dichotomicSearch(searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
19013
+ const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
19011
19014
  if (index === -1 ||
19012
- (verticalSearch && searchArray[0][index] === undefined) ||
19013
- (!verticalSearch && searchArray[index][nbRow - 1] === undefined)) {
19015
+ (verticalSearch && _searchArray[0][index] === undefined) ||
19016
+ (!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
19014
19017
  return valueNotAvailable(searchKey);
19015
19018
  }
19016
- if (resultRange === undefined) {
19017
- return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
19019
+ if (_resultRange[0].length === 0) {
19020
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
19018
19021
  }
19019
- nbCol = resultRange.length;
19020
- nbRow = resultRange[0].length;
19022
+ nbCol = _resultRange.length;
19023
+ nbRow = _resultRange[0].length;
19021
19024
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
19022
19025
  if (nbCol > 1) {
19023
19026
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
19024
- return resultRange[index][0];
19027
+ return _resultRange[index][0];
19025
19028
  }
19026
19029
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
19027
- return resultRange[0][index];
19030
+ return _resultRange[0][index];
19028
19031
  },
19029
19032
  isExported: true,
19030
19033
  };
@@ -19041,28 +19044,29 @@ stores.inject(MyMetaStore, storeInstance);
19041
19044
  ],
19042
19045
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
19043
19046
  let _searchType = toNumber(searchType, this.locale);
19044
- const nbCol = range.length;
19045
- const nbRow = range[0].length;
19047
+ const _range = toMatrix(range);
19048
+ const nbCol = _range.length;
19049
+ const nbRow = _range[0].length;
19046
19050
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
19047
19051
  let index = -1;
19048
19052
  const getElement = nbCol === 1
19049
- ? (range, index) => range[0][index].value
19050
- : (range, index) => range[index][0].value;
19051
- const rangeLen = nbCol === 1 ? range[0].length : range.length;
19053
+ ? (_range, index) => _range[0][index].value
19054
+ : (_range, index) => _range[index][0].value;
19055
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
19052
19056
  _searchType = Math.sign(_searchType);
19053
19057
  switch (_searchType) {
19054
19058
  case 1:
19055
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
19059
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
19056
19060
  break;
19057
19061
  case 0:
19058
- index = linearSearch(range, searchKey, "wildcard", rangeLen, getElement);
19062
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
19059
19063
  break;
19060
19064
  case -1:
19061
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
19065
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
19062
19066
  break;
19063
19067
  }
19064
- if ((nbCol === 1 && range[0][index] === undefined) ||
19065
- (nbCol !== 1 && range[index] === undefined)) {
19068
+ if ((nbCol === 1 && _range[0][index] === undefined) ||
19069
+ (nbCol !== 1 && _range[index] === undefined)) {
19066
19070
  return valueNotAvailable(searchKey);
19067
19071
  }
19068
19072
  return index + 1;
@@ -19116,16 +19120,17 @@ stores.inject(MyMetaStore, storeInstance);
19116
19120
  ],
19117
19121
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
19118
19122
  const _index = Math.trunc(toNumber(index?.value, this.locale));
19119
- assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
19123
+ const _range = toMatrix(range);
19124
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
19120
19125
  if (searchKey && isEvaluationError(searchKey.value)) {
19121
19126
  return searchKey;
19122
19127
  }
19123
19128
  const getValueFromRange = (range, index) => range[0][index].value;
19124
19129
  const _isSorted = toBoolean(isSorted.value);
19125
19130
  const rowIndex = _isSorted
19126
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range[0].length, getValueFromRange)
19127
- : linearSearch(range, searchKey, "wildcard", range[0].length, getValueFromRange);
19128
- const value = range[_index - 1][rowIndex];
19131
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
19132
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
19133
+ const value = _range[_index - 1][rowIndex];
19129
19134
  if (value === undefined) {
19130
19135
  return valueNotAvailable(searchKey);
19131
19136
  }
@@ -19162,30 +19167,32 @@ stores.inject(MyMetaStore, storeInstance);
19162
19167
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
19163
19168
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
19164
19169
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
19165
- assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
19170
+ const _lookupRange = toMatrix(lookupRange);
19171
+ const _returnRange = toMatrix(returnRange);
19172
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
19166
19173
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
19167
19174
  assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
19168
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
19175
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
19169
19176
  assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
19170
19177
  assert(() => lookupDirection === "col"
19171
- ? returnRange[0].length === lookupRange[0].length
19172
- : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
19178
+ ? _returnRange[0].length === _lookupRange[0].length
19179
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
19173
19180
  if (searchKey && isEvaluationError(searchKey.value)) {
19174
19181
  return [[searchKey]];
19175
19182
  }
19176
19183
  const getElement = lookupDirection === "col"
19177
19184
  ? (range, index) => range[0][index].value
19178
19185
  : (range, index) => range[index][0].value;
19179
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
19186
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
19180
19187
  const mode = MATCH_MODE[_matchMode];
19181
19188
  const reverseSearch = _searchMode === -1;
19182
19189
  const index = _searchMode === 2 || _searchMode === -2
19183
- ? dichotomicSearch(lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
19184
- : linearSearch(lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
19190
+ ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
19191
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
19185
19192
  if (index !== -1) {
19186
19193
  return lookupDirection === "col"
19187
- ? returnRange.map((col) => [col[index]])
19188
- : [returnRange[index]];
19194
+ ? _returnRange.map((col) => [col[index]])
19195
+ : [_returnRange[index]];
19189
19196
  }
19190
19197
  if (defaultValue === undefined) {
19191
19198
  return valueNotAvailable(searchKey);
@@ -41219,11 +41226,10 @@ stores.inject(MyMetaStore, storeInstance);
41219
41226
  switch (layer) {
41220
41227
  case "Background":
41221
41228
  this.drawGlobalBackground(renderingContext);
41222
- for (const zone of this.getters.getAllActiveViewportsZones()) {
41229
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
41223
41230
  const { ctx } = renderingContext;
41224
41231
  ctx.save();
41225
41232
  ctx.beginPath();
41226
- const rect = this.getters.getVisibleRect(zone);
41227
41233
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
41228
41234
  ctx.clip();
41229
41235
  const boxes = this.getGridBoxes(zone);
@@ -41493,10 +41499,8 @@ stores.inject(MyMetaStore, storeInstance);
41493
41499
  const { ctx, thinLineWidth } = renderingContext;
41494
41500
  const visibleCols = this.getters.getSheetViewVisibleCols();
41495
41501
  const left = visibleCols[0];
41496
- const right = visibleCols[visibleCols.length - 1];
41497
41502
  const visibleRows = this.getters.getSheetViewVisibleRows();
41498
41503
  const top = visibleRows[0];
41499
- const bottom = visibleRows[visibleRows.length - 1];
41500
41504
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
41501
41505
  const selection = this.getters.getSelectedZones();
41502
41506
  const selectedCols = getZonesCols(selection);
@@ -41512,7 +41516,7 @@ stores.inject(MyMetaStore, storeInstance);
41512
41516
  ctx.lineWidth = thinLineWidth;
41513
41517
  ctx.strokeStyle = "#333";
41514
41518
  // Columns headers background
41515
- for (let col = left; col <= right; col++) {
41519
+ for (const col of visibleCols) {
41516
41520
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
41517
41521
  const { x, width } = this.getters.getVisibleRect(colZone);
41518
41522
  const isColActive = activeCols.has(col);
@@ -41529,7 +41533,7 @@ stores.inject(MyMetaStore, storeInstance);
41529
41533
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
41530
41534
  }
41531
41535
  // Rows headers background
41532
- for (let row = top; row <= bottom; row++) {
41536
+ for (const row of visibleRows) {
41533
41537
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
41534
41538
  const { y, height } = this.getters.getVisibleRect(rowZone);
41535
41539
  const isRowActive = activeRows.has(row);
@@ -41555,21 +41559,21 @@ stores.inject(MyMetaStore, storeInstance);
41555
41559
  ctx.stroke();
41556
41560
  ctx.beginPath();
41557
41561
  // column text + separator
41558
- for (const i of visibleCols) {
41559
- const colSize = this.getters.getColSize(sheetId, i);
41560
- const colName = numberToLetters(i);
41561
- ctx.fillStyle = activeCols.has(i) ? "#fff" : TEXT_HEADER_COLOR;
41562
- let colStart = this.getHeaderOffset("COL", left, i);
41562
+ for (const col of visibleCols) {
41563
+ const colSize = this.getters.getColSize(sheetId, col);
41564
+ const colName = numberToLetters(col);
41565
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
41566
+ let colStart = this.getHeaderOffset("COL", left, col);
41563
41567
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
41564
41568
  ctx.moveTo(colStart + colSize, 0);
41565
41569
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
41566
41570
  }
41567
41571
  // row text + separator
41568
- for (const i of visibleRows) {
41569
- const rowSize = this.getters.getRowSize(sheetId, i);
41570
- ctx.fillStyle = activeRows.has(i) ? "#fff" : TEXT_HEADER_COLOR;
41571
- let rowStart = this.getHeaderOffset("ROW", top, i);
41572
- ctx.fillText(String(i + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
41572
+ for (const row of visibleRows) {
41573
+ const rowSize = this.getters.getRowSize(sheetId, row);
41574
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
41575
+ let rowStart = this.getHeaderOffset("ROW", top, row);
41576
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
41573
41577
  ctx.moveTo(0, rowStart + rowSize);
41574
41578
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
41575
41579
  }
@@ -41867,6 +41871,9 @@ stores.inject(MyMetaStore, storeInstance);
41867
41871
  canvas.width = width * dpr;
41868
41872
  canvas.height = height * dpr;
41869
41873
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
41874
+ if (width === 0 || height === 0) {
41875
+ return;
41876
+ }
41870
41877
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
41871
41878
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
41872
41879
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -47599,7 +47606,7 @@ stores.inject(MyMetaStore, storeInstance);
47599
47606
  getCommonSides(border1, border2) {
47600
47607
  const commonBorder = {};
47601
47608
  for (let side of ["top", "bottom", "left", "right"]) {
47602
- if (border1[side] && border1[side] === border2[side]) {
47609
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
47603
47610
  commonBorder[side] = border1[side];
47604
47611
  }
47605
47612
  }
@@ -60942,8 +60949,17 @@ stores.inject(MyMetaStore, storeInstance);
60942
60949
  this.getters = getters;
60943
60950
  this.sheetId = sheetId;
60944
60951
  this.boundaries = boundaries;
60945
- this.viewportWidth = sizeInGrid.width;
60946
- this.viewportHeight = sizeInGrid.height;
60952
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
60953
+ throw new Error("Viewport size cannot be negative");
60954
+ }
60955
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
60956
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
60957
+ this.top = boundaries.top;
60958
+ this.bottom = boundaries.bottom;
60959
+ this.left = boundaries.left;
60960
+ this.right = boundaries.right;
60961
+ this.offsetX = offsets.x;
60962
+ this.offsetY = offsets.y;
60947
60963
  this.offsetScrollbarX = offsets.x;
60948
60964
  this.offsetScrollbarY = offsets.y;
60949
60965
  this.canScrollVertically = options.canScrollVertically;
@@ -60986,9 +61002,9 @@ stores.inject(MyMetaStore, storeInstance);
60986
61002
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
60987
61003
  );
60988
61004
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
60989
- }
60990
- if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
60991
- height += FOOTER_HEIGHT;
61005
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
61006
+ height += FOOTER_HEIGHT;
61007
+ }
60992
61008
  }
60993
61009
  return { width, height };
60994
61010
  }
@@ -61129,6 +61145,9 @@ stores.inject(MyMetaStore, storeInstance);
61129
61145
  !this.getters.isRowHidden(this.sheetId, row));
61130
61146
  }
61131
61147
  searchHeaderIndex(dimension, position, startIndex = 0) {
61148
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
61149
+ return -1;
61150
+ }
61132
61151
  const sheetId = this.sheetId;
61133
61152
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
61134
61153
  // using a binary search:
@@ -61165,7 +61184,7 @@ stores.inject(MyMetaStore, storeInstance);
61165
61184
  this.adjustViewportZoneY();
61166
61185
  }
61167
61186
  /** Corrects the viewport's horizontal offset based on the current structure
61168
- * To make sure that at least on column is visible inside the viewport.
61187
+ * To make sure that at least one column is visible inside the viewport.
61169
61188
  */
61170
61189
  adjustViewportOffsetX() {
61171
61190
  if (this.canScrollHorizontally) {
@@ -61177,7 +61196,7 @@ stores.inject(MyMetaStore, storeInstance);
61177
61196
  this.adjustViewportZoneX();
61178
61197
  }
61179
61198
  /** Corrects the viewport's vertical offset based on the current structure
61180
- * To make sure that at least on row is visible inside the viewport.
61199
+ * To make sure that at least one row is visible inside the viewport.
61181
61200
  */
61182
61201
  adjustViewportOffsetY() {
61183
61202
  if (this.canScrollVertically) {
@@ -61194,11 +61213,14 @@ stores.inject(MyMetaStore, storeInstance);
61194
61213
  const sheetId = this.sheetId;
61195
61214
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
61196
61215
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
61216
+ if (!this.viewportWidth) {
61217
+ return;
61218
+ }
61197
61219
  if (this.left === -1) {
61198
61220
  this.left = this.boundaries.left;
61199
61221
  }
61200
61222
  if (this.right === -1) {
61201
- this.right = this.getters.getNumberCols(sheetId) - 1;
61223
+ this.right = this.boundaries.right;
61202
61224
  }
61203
61225
  this.offsetX =
61204
61226
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -61210,11 +61232,14 @@ stores.inject(MyMetaStore, storeInstance);
61210
61232
  const sheetId = this.sheetId;
61211
61233
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
61212
61234
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
61235
+ if (!this.viewportHeight) {
61236
+ return;
61237
+ }
61213
61238
  if (this.top === -1) {
61214
61239
  this.top = this.boundaries.top;
61215
61240
  }
61216
61241
  if (this.bottom === -1) {
61217
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
61242
+ this.bottom = this.boundaries.bottom;
61218
61243
  }
61219
61244
  this.offsetY =
61220
61245
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -61288,7 +61313,7 @@ stores.inject(MyMetaStore, storeInstance);
61288
61313
  "isPositionVisible",
61289
61314
  "getColDimensionsInViewport",
61290
61315
  "getRowDimensionsInViewport",
61291
- "getAllActiveViewportsZones",
61316
+ "getAllActiveViewportsZonesAndRect",
61292
61317
  "getRect",
61293
61318
  ];
61294
61319
  viewports = {};
@@ -61521,12 +61546,12 @@ stores.inject(MyMetaStore, storeInstance);
61521
61546
  const sheetId = this.getters.getActiveSheetId();
61522
61547
  const viewports = this.getSubViewports(sheetId);
61523
61548
  //TODO ake another commit to eimprove this
61524
- return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
61549
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
61525
61550
  }
61526
61551
  getSheetViewVisibleRows() {
61527
61552
  const sheetId = this.getters.getActiveSheetId();
61528
61553
  const viewports = this.getSubViewports(sheetId);
61529
- return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
61554
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
61530
61555
  }
61531
61556
  /**
61532
61557
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -61569,19 +61594,19 @@ stores.inject(MyMetaStore, storeInstance);
61569
61594
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
61570
61595
  };
61571
61596
  }
61572
- getColRowOffsetInViewport(dimension, referenceIndex, index) {
61573
- const sheetId = this.getters.getActiveSheetId();
61574
- const visibleCols = this.getters.getSheetViewVisibleCols();
61575
- const visibleRows = this.getters.getSheetViewVisibleRows();
61576
- if (index < referenceIndex) {
61577
- return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
61597
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
61598
+ if (targetHeaderIndex < referenceHeaderIndex) {
61599
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
61578
61600
  }
61601
+ const sheetId = this.getters.getActiveSheetId();
61602
+ const visibleHeaders = dimension === "COL"
61603
+ ? this.getters.getSheetViewVisibleCols()
61604
+ : this.getters.getSheetViewVisibleRows();
61605
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
61606
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
61607
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
61579
61608
  let offset = 0;
61580
- const visibleIndexes = dimension === "COL" ? visibleCols : visibleRows;
61581
- for (let i = referenceIndex; i < index; i++) {
61582
- if (!visibleIndexes.includes(i)) {
61583
- continue;
61584
- }
61609
+ for (const i of relevantIndexes) {
61585
61610
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
61586
61611
  }
61587
61612
  return offset;
@@ -61628,7 +61653,7 @@ stores.inject(MyMetaStore, storeInstance);
61628
61653
  }
61629
61654
  return { canEdgeScroll, direction, delay };
61630
61655
  }
61631
- getEdgeScrollRow(y, previousY, tartingY) {
61656
+ getEdgeScrollRow(y, previousY, startingY) {
61632
61657
  let canEdgeScroll = false;
61633
61658
  let direction = 0;
61634
61659
  let delay = 0;
@@ -61649,7 +61674,7 @@ stores.inject(MyMetaStore, storeInstance);
61649
61674
  delay = scrollDelay(y - height);
61650
61675
  direction = 1;
61651
61676
  }
61652
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
61677
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
61653
61678
  // 2
61654
61679
  canEdgeScroll = true;
61655
61680
  delay = scrollDelay(offsetCorrectionY - y);
@@ -61675,13 +61700,7 @@ stores.inject(MyMetaStore, storeInstance);
61675
61700
  */
61676
61701
  getVisibleRectWithoutHeaders(zone) {
61677
61702
  const sheetId = this.getters.getActiveSheetId();
61678
- const viewportRects = this.getSubViewports(sheetId)
61679
- .map((viewport) => viewport.getVisibleRect(zone))
61680
- .filter(isDefined);
61681
- if (viewportRects.length === 0) {
61682
- return { x: 0, y: 0, width: 0, height: 0 };
61683
- }
61684
- return this.recomposeRect(viewportRects);
61703
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
61685
61704
  }
61686
61705
  /**
61687
61706
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -61689,13 +61708,7 @@ stores.inject(MyMetaStore, storeInstance);
61689
61708
  */
61690
61709
  getRect(zone) {
61691
61710
  const sheetId = this.getters.getActiveSheetId();
61692
- const viewportRects = this.getSubViewports(sheetId)
61693
- .map((viewport) => viewport.getFullRect(zone))
61694
- .filter(isDefined);
61695
- if (viewportRects.length === 0) {
61696
- return { x: 0, y: 0, width: 0, height: 0 };
61697
- }
61698
- const rect = this.recomposeRect(viewportRects);
61711
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
61699
61712
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
61700
61713
  }
61701
61714
  /**
@@ -61740,9 +61753,18 @@ stores.inject(MyMetaStore, storeInstance);
61740
61753
  end: start + (isRowHidden ? 0 : size),
61741
61754
  };
61742
61755
  }
61743
- getAllActiveViewportsZones() {
61756
+ getAllActiveViewportsZonesAndRect() {
61744
61757
  const sheetId = this.getters.getActiveSheetId();
61745
- return this.getSubViewports(sheetId);
61758
+ return this.getSubViewports(sheetId).map((viewport) => {
61759
+ return {
61760
+ zone: viewport,
61761
+ rect: {
61762
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
61763
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
61764
+ ...viewport.getMaxSize(),
61765
+ },
61766
+ };
61767
+ });
61746
61768
  }
61747
61769
  // ---------------------------------------------------------------------------
61748
61770
  // Private
@@ -61801,12 +61823,11 @@ stores.inject(MyMetaStore, storeInstance);
61801
61823
  }
61802
61824
  /** gets rid of deprecated sheetIds */
61803
61825
  cleanViewports() {
61804
- const sheetIds = this.getters.getSheetIds();
61805
- for (let sheetId of Object.keys(this.viewports)) {
61806
- if (!sheetIds.includes(sheetId)) {
61807
- delete this.viewports[sheetId];
61808
- }
61826
+ const newViewport = {};
61827
+ for (const sheetId of this.getters.getSheetIds()) {
61828
+ newViewport[sheetId] = this.viewports[sheetId];
61809
61829
  }
61830
+ this.viewports = newViewport;
61810
61831
  }
61811
61832
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
61812
61833
  this.sheetViewHeight = height;
@@ -61816,7 +61837,7 @@ stores.inject(MyMetaStore, storeInstance);
61816
61837
  this.recomputeViewports();
61817
61838
  }
61818
61839
  recomputeViewports() {
61819
- for (let sheetId of Object.keys(this.viewports)) {
61840
+ for (const sheetId of this.getters.getSheetIds()) {
61820
61841
  this.resetViewports(sheetId);
61821
61842
  }
61822
61843
  }
@@ -61838,8 +61859,10 @@ stores.inject(MyMetaStore, storeInstance);
61838
61859
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
61839
61860
  const nCols = this.getters.getNumberCols(sheetId);
61840
61861
  const nRows = this.getters.getNumberRows(sheetId);
61841
- const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
61842
- const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
61862
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
61863
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
61864
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
61865
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
61843
61866
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
61844
61867
  const canScrollHorizontally = xRatio < 1.0;
61845
61868
  const canScrollVertically = yRatio < 1.0;
@@ -61850,14 +61873,14 @@ stores.inject(MyMetaStore, storeInstance);
61850
61873
  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 })) ||
61851
61874
  undefined,
61852
61875
  topRight: (ySplit &&
61853
- 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 })) ||
61876
+ 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 })) ||
61854
61877
  undefined,
61855
61878
  bottomLeft: (xSplit &&
61856
- 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 })) ||
61879
+ 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 })) ||
61857
61880
  undefined,
61858
61881
  bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
61859
- width: this.sheetViewWidth - colOffset,
61860
- height: this.sheetViewHeight - rowOffset,
61882
+ width: unfrozenWidth,
61883
+ height: unfrozenHeight,
61861
61884
  }, { canScrollHorizontally, canScrollVertically }, {
61862
61885
  x: canScrollHorizontally ? previousOffset.x : 0,
61863
61886
  y: canScrollVertically ? previousOffset.y : 0,
@@ -61934,12 +61957,26 @@ stores.inject(MyMetaStore, storeInstance);
61934
61957
  const height = this.sheetViewHeight + this.gridOffsetY;
61935
61958
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
61936
61959
  }
61937
- recomposeRect(viewportRects) {
61938
- const x = Math.min(...viewportRects.map((rect) => rect.x));
61939
- const y = Math.min(...viewportRects.map((rect) => rect.y));
61940
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
61941
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
61942
- return { x, y, width, height };
61960
+ mapViewportsToRect(sheetId, rectCallBack) {
61961
+ let x = Infinity;
61962
+ let y = Infinity;
61963
+ let width = 0;
61964
+ let height = 0;
61965
+ let hasViewports = false;
61966
+ for (const viewport of this.getSubViewports(sheetId)) {
61967
+ const rect = rectCallBack(viewport);
61968
+ if (rect) {
61969
+ hasViewports = true;
61970
+ x = Math.min(x, rect.x);
61971
+ y = Math.min(y, rect.y);
61972
+ width = Math.max(width, rect.x + rect.width);
61973
+ height = Math.max(height, rect.y + rect.height);
61974
+ }
61975
+ }
61976
+ if (!hasViewports) {
61977
+ return { x: 0, y: 0, width: 0, height: 0 };
61978
+ }
61979
+ return { x, y, width: width - x, height: height - y };
61943
61980
  }
61944
61981
  }
61945
61982
 
@@ -68872,9 +68909,9 @@ stores.inject(MyMetaStore, storeInstance);
68872
68909
  exports.tokenize = tokenize;
68873
68910
 
68874
68911
 
68875
- __info__.version = "17.4.20";
68876
- __info__.date = "2025-01-31T08:00:07.103Z";
68877
- __info__.hash = "54a344a";
68912
+ __info__.version = "17.4.21";
68913
+ __info__.date = "2025-02-05T06:46:54.366Z";
68914
+ __info__.hash = "0c55e18";
68878
68915
 
68879
68916
 
68880
68917
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);