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