@odoo/o-spreadsheet 18.0.13 → 18.0.14

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 18.0.13
6
- * @date 2025-01-31T07:59:17.481Z
7
- * @hash f505971
5
+ * @version 18.0.14
6
+ * @date 2025-02-05T06:47:33.041Z
7
+ * @hash 90f2af4
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -18382,19 +18382,20 @@ const HLOOKUP = {
18382
18382
  description: _t("Horizontal lookup"),
18383
18383
  args: [
18384
18384
  arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18385
- 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.")),
18385
+ 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.")),
18386
18386
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18387
18387
  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.")),
18388
18388
  ],
18389
18389
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18390
18390
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18391
- assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18391
+ const _range = toMatrix(range);
18392
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18392
18393
  const getValueFromRange = (range, index) => range[index][0].value;
18393
18394
  const _isSorted = toBoolean(isSorted.value);
18394
18395
  const colIndex = _isSorted
18395
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range.length, getValueFromRange)
18396
- : linearSearch(range, searchKey, "wildcard", range.length, getValueFromRange, this.lookupCaches);
18397
- const col = range[colIndex];
18396
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
18397
+ : linearSearch(range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
18398
+ const col = _range[colIndex];
18398
18399
  if (col === undefined) {
18399
18400
  return valueNotAvailable(searchKey);
18400
18401
  }
@@ -18486,35 +18487,37 @@ const LOOKUP = {
18486
18487
  description: _t("Look up a value."),
18487
18488
  args: [
18488
18489
  arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18489
- 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.")),
18490
- 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.")),
18490
+ 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.")),
18491
+ 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.")),
18491
18492
  ],
18492
18493
  compute: function (searchKey, searchArray, resultRange) {
18493
- let nbCol = searchArray.length;
18494
- let nbRow = searchArray[0].length;
18494
+ const _searchArray = toMatrix(searchArray);
18495
+ const _resultRange = toMatrix(resultRange);
18496
+ let nbCol = _searchArray.length;
18497
+ let nbRow = _searchArray[0].length;
18495
18498
  const verticalSearch = nbRow >= nbCol;
18496
18499
  const getElement = verticalSearch
18497
18500
  ? (range, index) => range[0][index].value
18498
18501
  : (range, index) => range[index][0].value;
18499
18502
  const rangeLength = verticalSearch ? nbRow : nbCol;
18500
- const index = dichotomicSearch(searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
18503
+ const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
18501
18504
  if (index === -1 ||
18502
- (verticalSearch && searchArray[0][index] === undefined) ||
18503
- (!verticalSearch && searchArray[index][nbRow - 1] === undefined)) {
18505
+ (verticalSearch && _searchArray[0][index] === undefined) ||
18506
+ (!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
18504
18507
  return valueNotAvailable(searchKey);
18505
18508
  }
18506
- if (resultRange === undefined) {
18507
- return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
18509
+ if (_resultRange[0].length === 0) {
18510
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
18508
18511
  }
18509
- nbCol = resultRange.length;
18510
- nbRow = resultRange[0].length;
18512
+ nbCol = _resultRange.length;
18513
+ nbRow = _resultRange[0].length;
18511
18514
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
18512
18515
  if (nbCol > 1) {
18513
18516
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
18514
- return resultRange[index][0];
18517
+ return _resultRange[index][0];
18515
18518
  }
18516
18519
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
18517
- return resultRange[0][index];
18520
+ return _resultRange[0][index];
18518
18521
  },
18519
18522
  isExported: true,
18520
18523
  };
@@ -18531,28 +18534,29 @@ const MATCH = {
18531
18534
  ],
18532
18535
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
18533
18536
  let _searchType = toNumber(searchType, this.locale);
18534
- const nbCol = range.length;
18535
- const nbRow = range[0].length;
18537
+ const _range = toMatrix(range);
18538
+ const nbCol = _range.length;
18539
+ const nbRow = _range[0].length;
18536
18540
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
18537
18541
  let index = -1;
18538
18542
  const getElement = nbCol === 1
18539
- ? (range, index) => range[0][index].value
18540
- : (range, index) => range[index][0].value;
18541
- const rangeLen = nbCol === 1 ? range[0].length : range.length;
18543
+ ? (_range, index) => _range[0][index].value
18544
+ : (_range, index) => _range[index][0].value;
18545
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
18542
18546
  _searchType = Math.sign(_searchType);
18543
18547
  switch (_searchType) {
18544
18548
  case 1:
18545
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18549
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18546
18550
  break;
18547
18551
  case 0:
18548
- index = linearSearch(range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
18552
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
18549
18553
  break;
18550
18554
  case -1:
18551
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18555
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18552
18556
  break;
18553
18557
  }
18554
- if ((nbCol === 1 && range[0][index] === undefined) ||
18555
- (nbCol !== 1 && range[index] === undefined)) {
18558
+ if ((nbCol === 1 && _range[0][index] === undefined) ||
18559
+ (nbCol !== 1 && _range[index] === undefined)) {
18556
18560
  return valueNotAvailable(searchKey);
18557
18561
  }
18558
18562
  return index + 1;
@@ -18607,13 +18611,14 @@ const VLOOKUP = {
18607
18611
  ],
18608
18612
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18609
18613
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18610
- assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18614
+ const _range = toMatrix(range);
18615
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18611
18616
  const getValueFromRange = (range, index) => range[0][index].value;
18612
18617
  const _isSorted = toBoolean(isSorted.value);
18613
18618
  const rowIndex = _isSorted
18614
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range[0].length, getValueFromRange)
18615
- : linearSearch(range, searchKey, "wildcard", range[0].length, getValueFromRange, this.lookupCaches);
18616
- const value = range[_index - 1][rowIndex];
18619
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18620
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
18621
+ const value = _range[_index - 1][rowIndex];
18617
18622
  if (value === undefined) {
18618
18623
  return valueNotAvailable(searchKey);
18619
18624
  }
@@ -18650,27 +18655,29 @@ const XLOOKUP = {
18650
18655
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18651
18656
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18652
18657
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
18653
- assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18658
+ const _lookupRange = toMatrix(lookupRange);
18659
+ const _returnRange = toMatrix(returnRange);
18660
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18654
18661
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
18655
18662
  assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
18656
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
18663
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
18657
18664
  assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
18658
18665
  assert(() => lookupDirection === "col"
18659
- ? returnRange[0].length === lookupRange[0].length
18660
- : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18666
+ ? _returnRange[0].length === _lookupRange[0].length
18667
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18661
18668
  const getElement = lookupDirection === "col"
18662
18669
  ? (range, index) => range[0][index].value
18663
18670
  : (range, index) => range[index][0].value;
18664
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
18671
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
18665
18672
  const mode = MATCH_MODE[_matchMode];
18666
18673
  const reverseSearch = _searchMode === -1;
18667
18674
  const index = _searchMode === 2 || _searchMode === -2
18668
- ? dichotomicSearch(lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18669
- : linearSearch(lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
18675
+ ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18676
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
18670
18677
  if (index !== -1) {
18671
18678
  return lookupDirection === "col"
18672
- ? returnRange.map((col) => [col[index]])
18673
- : [returnRange[index]];
18679
+ ? _returnRange.map((col) => [col[index]])
18680
+ : [_returnRange[index]];
18674
18681
  }
18675
18682
  if (defaultValue === undefined) {
18676
18683
  return valueNotAvailable(searchKey);
@@ -48476,11 +48483,10 @@ class GridRenderer {
48476
48483
  switch (layer) {
48477
48484
  case "Background":
48478
48485
  this.drawGlobalBackground(renderingContext);
48479
- for (const zone of this.getters.getAllActiveViewportsZones()) {
48486
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
48480
48487
  const { ctx } = renderingContext;
48481
48488
  ctx.save();
48482
48489
  ctx.beginPath();
48483
- const rect = this.getters.getVisibleRect(zone);
48484
48490
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
48485
48491
  ctx.clip();
48486
48492
  const boxes = this.getGridBoxes(zone);
@@ -48756,10 +48762,8 @@ class GridRenderer {
48756
48762
  const { ctx, thinLineWidth } = renderingContext;
48757
48763
  const visibleCols = this.getters.getSheetViewVisibleCols();
48758
48764
  const left = visibleCols[0];
48759
- const right = visibleCols[visibleCols.length - 1];
48760
48765
  const visibleRows = this.getters.getSheetViewVisibleRows();
48761
48766
  const top = visibleRows[0];
48762
- const bottom = visibleRows[visibleRows.length - 1];
48763
48767
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
48764
48768
  const selection = this.getters.getSelectedZones();
48765
48769
  const selectedCols = getZonesCols(selection);
@@ -48775,7 +48779,7 @@ class GridRenderer {
48775
48779
  ctx.lineWidth = thinLineWidth;
48776
48780
  ctx.strokeStyle = "#333";
48777
48781
  // Columns headers background
48778
- for (let col = left; col <= right; col++) {
48782
+ for (const col of visibleCols) {
48779
48783
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
48780
48784
  const { x, width } = this.getters.getVisibleRect(colZone);
48781
48785
  const isColActive = activeCols.has(col);
@@ -48792,7 +48796,7 @@ class GridRenderer {
48792
48796
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
48793
48797
  }
48794
48798
  // Rows headers background
48795
- for (let row = top; row <= bottom; row++) {
48799
+ for (const row of visibleRows) {
48796
48800
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
48797
48801
  const { y, height } = this.getters.getVisibleRect(rowZone);
48798
48802
  const isRowActive = activeRows.has(row);
@@ -48818,21 +48822,21 @@ class GridRenderer {
48818
48822
  ctx.stroke();
48819
48823
  ctx.beginPath();
48820
48824
  // column text + separator
48821
- for (const i of visibleCols) {
48822
- const colSize = this.getters.getColSize(sheetId, i);
48823
- const colName = numberToLetters(i);
48824
- ctx.fillStyle = activeCols.has(i) ? "#fff" : TEXT_HEADER_COLOR;
48825
- let colStart = this.getHeaderOffset("COL", left, i);
48825
+ for (const col of visibleCols) {
48826
+ const colSize = this.getters.getColSize(sheetId, col);
48827
+ const colName = numberToLetters(col);
48828
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
48829
+ let colStart = this.getHeaderOffset("COL", left, col);
48826
48830
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
48827
48831
  ctx.moveTo(colStart + colSize, 0);
48828
48832
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
48829
48833
  }
48830
48834
  // row text + separator
48831
- for (const i of visibleRows) {
48832
- const rowSize = this.getters.getRowSize(sheetId, i);
48833
- ctx.fillStyle = activeRows.has(i) ? "#fff" : TEXT_HEADER_COLOR;
48834
- let rowStart = this.getHeaderOffset("ROW", top, i);
48835
- ctx.fillText(String(i + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
48835
+ for (const row of visibleRows) {
48836
+ const rowSize = this.getters.getRowSize(sheetId, row);
48837
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
48838
+ let rowStart = this.getHeaderOffset("ROW", top, row);
48839
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
48836
48840
  ctx.moveTo(0, rowStart + rowSize);
48837
48841
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
48838
48842
  }
@@ -49132,6 +49136,9 @@ function useGridDrawing(refName, model, canvasSize) {
49132
49136
  canvas.width = width * dpr;
49133
49137
  canvas.height = height * dpr;
49134
49138
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
49139
+ if (width === 0 || height === 0) {
49140
+ return;
49141
+ }
49135
49142
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
49136
49143
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
49137
49144
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -50703,7 +50710,7 @@ class BordersPlugin extends CorePlugin {
50703
50710
  getCommonSides(border1, border2) {
50704
50711
  const commonBorder = {};
50705
50712
  for (let side of ["top", "bottom", "left", "right"]) {
50706
- if (border1[side] && border1[side] === border2[side]) {
50713
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
50707
50714
  commonBorder[side] = border1[side];
50708
50715
  }
50709
50716
  }
@@ -64973,8 +64980,17 @@ class InternalViewport {
64973
64980
  this.getters = getters;
64974
64981
  this.sheetId = sheetId;
64975
64982
  this.boundaries = boundaries;
64976
- this.viewportWidth = sizeInGrid.width;
64977
- this.viewportHeight = sizeInGrid.height;
64983
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
64984
+ throw new Error("Viewport size cannot be negative");
64985
+ }
64986
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
64987
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
64988
+ this.top = boundaries.top;
64989
+ this.bottom = boundaries.bottom;
64990
+ this.left = boundaries.left;
64991
+ this.right = boundaries.right;
64992
+ this.offsetX = offsets.x;
64993
+ this.offsetY = offsets.y;
64978
64994
  this.offsetScrollbarX = offsets.x;
64979
64995
  this.offsetScrollbarY = offsets.y;
64980
64996
  this.canScrollVertically = options.canScrollVertically;
@@ -65017,9 +65033,9 @@ class InternalViewport {
65017
65033
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
65018
65034
  );
65019
65035
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
65020
- }
65021
- if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
65022
- height += FOOTER_HEIGHT;
65036
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
65037
+ height += FOOTER_HEIGHT;
65038
+ }
65023
65039
  }
65024
65040
  return { width, height };
65025
65041
  }
@@ -65160,6 +65176,9 @@ class InternalViewport {
65160
65176
  !this.getters.isRowHidden(this.sheetId, row));
65161
65177
  }
65162
65178
  searchHeaderIndex(dimension, position, startIndex = 0) {
65179
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
65180
+ return -1;
65181
+ }
65163
65182
  const sheetId = this.sheetId;
65164
65183
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
65165
65184
  // using a binary search:
@@ -65196,7 +65215,7 @@ class InternalViewport {
65196
65215
  this.adjustViewportZoneY();
65197
65216
  }
65198
65217
  /** Corrects the viewport's horizontal offset based on the current structure
65199
- * To make sure that at least on column is visible inside the viewport.
65218
+ * To make sure that at least one column is visible inside the viewport.
65200
65219
  */
65201
65220
  adjustViewportOffsetX() {
65202
65221
  if (this.canScrollHorizontally) {
@@ -65208,7 +65227,7 @@ class InternalViewport {
65208
65227
  this.adjustViewportZoneX();
65209
65228
  }
65210
65229
  /** Corrects the viewport's vertical offset based on the current structure
65211
- * To make sure that at least on row is visible inside the viewport.
65230
+ * To make sure that at least one row is visible inside the viewport.
65212
65231
  */
65213
65232
  adjustViewportOffsetY() {
65214
65233
  if (this.canScrollVertically) {
@@ -65225,11 +65244,14 @@ class InternalViewport {
65225
65244
  const sheetId = this.sheetId;
65226
65245
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
65227
65246
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
65247
+ if (!this.viewportWidth) {
65248
+ return;
65249
+ }
65228
65250
  if (this.left === -1) {
65229
65251
  this.left = this.boundaries.left;
65230
65252
  }
65231
65253
  if (this.right === -1) {
65232
- this.right = this.getters.getNumberCols(sheetId) - 1;
65254
+ this.right = this.boundaries.right;
65233
65255
  }
65234
65256
  this.offsetX =
65235
65257
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -65241,11 +65263,14 @@ class InternalViewport {
65241
65263
  const sheetId = this.sheetId;
65242
65264
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
65243
65265
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
65266
+ if (!this.viewportHeight) {
65267
+ return;
65268
+ }
65244
65269
  if (this.top === -1) {
65245
65270
  this.top = this.boundaries.top;
65246
65271
  }
65247
65272
  if (this.bottom === -1) {
65248
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
65273
+ this.bottom = this.boundaries.bottom;
65249
65274
  }
65250
65275
  this.offsetY =
65251
65276
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -65319,7 +65344,7 @@ class SheetViewPlugin extends UIPlugin {
65319
65344
  "isPositionVisible",
65320
65345
  "getColDimensionsInViewport",
65321
65346
  "getRowDimensionsInViewport",
65322
- "getAllActiveViewportsZones",
65347
+ "getAllActiveViewportsZonesAndRect",
65323
65348
  "getRect",
65324
65349
  ];
65325
65350
  viewports = {};
@@ -65552,12 +65577,12 @@ class SheetViewPlugin extends UIPlugin {
65552
65577
  const sheetId = this.getters.getActiveSheetId();
65553
65578
  const viewports = this.getSubViewports(sheetId);
65554
65579
  //TODO ake another commit to eimprove this
65555
- return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
65580
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
65556
65581
  }
65557
65582
  getSheetViewVisibleRows() {
65558
65583
  const sheetId = this.getters.getActiveSheetId();
65559
65584
  const viewports = this.getSubViewports(sheetId);
65560
- return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
65585
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
65561
65586
  }
65562
65587
  /**
65563
65588
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -65600,19 +65625,19 @@ class SheetViewPlugin extends UIPlugin {
65600
65625
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
65601
65626
  };
65602
65627
  }
65603
- getColRowOffsetInViewport(dimension, referenceIndex, index) {
65604
- const sheetId = this.getters.getActiveSheetId();
65605
- const visibleCols = this.getters.getSheetViewVisibleCols();
65606
- const visibleRows = this.getters.getSheetViewVisibleRows();
65607
- if (index < referenceIndex) {
65608
- return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
65628
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
65629
+ if (targetHeaderIndex < referenceHeaderIndex) {
65630
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
65609
65631
  }
65632
+ const sheetId = this.getters.getActiveSheetId();
65633
+ const visibleHeaders = dimension === "COL"
65634
+ ? this.getters.getSheetViewVisibleCols()
65635
+ : this.getters.getSheetViewVisibleRows();
65636
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
65637
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
65638
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
65610
65639
  let offset = 0;
65611
- const visibleIndexes = dimension === "COL" ? visibleCols : visibleRows;
65612
- for (let i = referenceIndex; i < index; i++) {
65613
- if (!visibleIndexes.includes(i)) {
65614
- continue;
65615
- }
65640
+ for (const i of relevantIndexes) {
65616
65641
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
65617
65642
  }
65618
65643
  return offset;
@@ -65659,7 +65684,7 @@ class SheetViewPlugin extends UIPlugin {
65659
65684
  }
65660
65685
  return { canEdgeScroll, direction, delay };
65661
65686
  }
65662
- getEdgeScrollRow(y, previousY, tartingY) {
65687
+ getEdgeScrollRow(y, previousY, startingY) {
65663
65688
  let canEdgeScroll = false;
65664
65689
  let direction = 0;
65665
65690
  let delay = 0;
@@ -65680,7 +65705,7 @@ class SheetViewPlugin extends UIPlugin {
65680
65705
  delay = scrollDelay(y - height);
65681
65706
  direction = 1;
65682
65707
  }
65683
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
65708
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
65684
65709
  // 2
65685
65710
  canEdgeScroll = true;
65686
65711
  delay = scrollDelay(offsetCorrectionY - y);
@@ -65706,13 +65731,7 @@ class SheetViewPlugin extends UIPlugin {
65706
65731
  */
65707
65732
  getVisibleRectWithoutHeaders(zone) {
65708
65733
  const sheetId = this.getters.getActiveSheetId();
65709
- const viewportRects = this.getSubViewports(sheetId)
65710
- .map((viewport) => viewport.getVisibleRect(zone))
65711
- .filter(isDefined);
65712
- if (viewportRects.length === 0) {
65713
- return { x: 0, y: 0, width: 0, height: 0 };
65714
- }
65715
- return this.recomposeRect(viewportRects);
65734
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
65716
65735
  }
65717
65736
  /**
65718
65737
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -65720,13 +65739,7 @@ class SheetViewPlugin extends UIPlugin {
65720
65739
  */
65721
65740
  getRect(zone) {
65722
65741
  const sheetId = this.getters.getActiveSheetId();
65723
- const viewportRects = this.getSubViewports(sheetId)
65724
- .map((viewport) => viewport.getFullRect(zone))
65725
- .filter(isDefined);
65726
- if (viewportRects.length === 0) {
65727
- return { x: 0, y: 0, width: 0, height: 0 };
65728
- }
65729
- const rect = this.recomposeRect(viewportRects);
65742
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
65730
65743
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
65731
65744
  }
65732
65745
  /**
@@ -65771,9 +65784,18 @@ class SheetViewPlugin extends UIPlugin {
65771
65784
  end: start + (isRowHidden ? 0 : size),
65772
65785
  };
65773
65786
  }
65774
- getAllActiveViewportsZones() {
65787
+ getAllActiveViewportsZonesAndRect() {
65775
65788
  const sheetId = this.getters.getActiveSheetId();
65776
- return this.getSubViewports(sheetId);
65789
+ return this.getSubViewports(sheetId).map((viewport) => {
65790
+ return {
65791
+ zone: viewport,
65792
+ rect: {
65793
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
65794
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
65795
+ ...viewport.getMaxSize(),
65796
+ },
65797
+ };
65798
+ });
65777
65799
  }
65778
65800
  // ---------------------------------------------------------------------------
65779
65801
  // Private
@@ -65832,12 +65854,11 @@ class SheetViewPlugin extends UIPlugin {
65832
65854
  }
65833
65855
  /** gets rid of deprecated sheetIds */
65834
65856
  cleanViewports() {
65835
- const sheetIds = this.getters.getSheetIds();
65836
- for (let sheetId of Object.keys(this.viewports)) {
65837
- if (!sheetIds.includes(sheetId)) {
65838
- delete this.viewports[sheetId];
65839
- }
65857
+ const newViewport = {};
65858
+ for (const sheetId of this.getters.getSheetIds()) {
65859
+ newViewport[sheetId] = this.viewports[sheetId];
65840
65860
  }
65861
+ this.viewports = newViewport;
65841
65862
  }
65842
65863
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
65843
65864
  this.sheetViewHeight = height;
@@ -65847,7 +65868,7 @@ class SheetViewPlugin extends UIPlugin {
65847
65868
  this.recomputeViewports();
65848
65869
  }
65849
65870
  recomputeViewports() {
65850
- for (let sheetId of Object.keys(this.viewports)) {
65871
+ for (const sheetId of this.getters.getSheetIds()) {
65851
65872
  this.resetViewports(sheetId);
65852
65873
  }
65853
65874
  }
@@ -65869,8 +65890,10 @@ class SheetViewPlugin extends UIPlugin {
65869
65890
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
65870
65891
  const nCols = this.getters.getNumberCols(sheetId);
65871
65892
  const nRows = this.getters.getNumberRows(sheetId);
65872
- const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
65873
- const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
65893
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
65894
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
65895
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
65896
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
65874
65897
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
65875
65898
  const canScrollHorizontally = xRatio < 1.0;
65876
65899
  const canScrollVertically = yRatio < 1.0;
@@ -65881,14 +65904,14 @@ class SheetViewPlugin extends UIPlugin {
65881
65904
  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 })) ||
65882
65905
  undefined,
65883
65906
  topRight: (ySplit &&
65884
- 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 })) ||
65907
+ 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 })) ||
65885
65908
  undefined,
65886
65909
  bottomLeft: (xSplit &&
65887
- 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 })) ||
65910
+ 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 })) ||
65888
65911
  undefined,
65889
65912
  bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
65890
- width: this.sheetViewWidth - colOffset,
65891
- height: this.sheetViewHeight - rowOffset,
65913
+ width: unfrozenWidth,
65914
+ height: unfrozenHeight,
65892
65915
  }, { canScrollHorizontally, canScrollVertically }, {
65893
65916
  x: canScrollHorizontally ? previousOffset.x : 0,
65894
65917
  y: canScrollVertically ? previousOffset.y : 0,
@@ -65965,12 +65988,26 @@ class SheetViewPlugin extends UIPlugin {
65965
65988
  const height = this.sheetViewHeight + this.gridOffsetY;
65966
65989
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
65967
65990
  }
65968
- recomposeRect(viewportRects) {
65969
- const x = Math.min(...viewportRects.map((rect) => rect.x));
65970
- const y = Math.min(...viewportRects.map((rect) => rect.y));
65971
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
65972
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
65973
- return { x, y, width, height };
65991
+ mapViewportsToRect(sheetId, rectCallBack) {
65992
+ let x = Infinity;
65993
+ let y = Infinity;
65994
+ let width = 0;
65995
+ let height = 0;
65996
+ let hasViewports = false;
65997
+ for (const viewport of this.getSubViewports(sheetId)) {
65998
+ const rect = rectCallBack(viewport);
65999
+ if (rect) {
66000
+ hasViewports = true;
66001
+ x = Math.min(x, rect.x);
66002
+ y = Math.min(y, rect.y);
66003
+ width = Math.max(width, rect.x + rect.width);
66004
+ height = Math.max(height, rect.y + rect.height);
66005
+ }
66006
+ }
66007
+ if (!hasViewports) {
66008
+ return { x: 0, y: 0, width: 0, height: 0 };
66009
+ }
66010
+ return { x, y, width: width - x, height: height - y };
65974
66011
  }
65975
66012
  }
65976
66013
 
@@ -73088,6 +73125,6 @@ const constants = {
73088
73125
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
73089
73126
 
73090
73127
 
73091
- __info__.version = "18.0.13";
73092
- __info__.date = "2025-01-31T07:59:17.481Z";
73093
- __info__.hash = "f505971";
73128
+ __info__.version = "18.0.14";
73129
+ __info__.date = "2025-02-05T06:47:33.041Z";
73130
+ __info__.hash = "90f2af4";