@odoo/o-spreadsheet 17.0.47 → 17.0.49

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.0.47
6
- * @date 2025-01-31T07:56:50.980Z
7
- * @hash a22bce2
5
+ * @version 17.0.49
6
+ * @date 2025-02-10T08:55:47.771Z
7
+ * @hash 1049319
8
8
  */
9
9
 
10
10
  'use strict';
@@ -688,9 +688,16 @@ function deepEquals(o1, o2) {
688
688
  }
689
689
  return true;
690
690
  }
691
- /** Check if the given array contains all the values of the other array. */
691
+ /**
692
+ * Check if the given array contains all the values of the other array.
693
+ * It makes the assumption that both array do not contain duplicates.
694
+ */
692
695
  function includesAll(arr, values) {
693
- return values.every((value) => arr.includes(value));
696
+ if (arr.length < values.length) {
697
+ return false;
698
+ }
699
+ const set = new Set(arr);
700
+ return values.every((value) => set.has(value));
694
701
  }
695
702
  /**
696
703
  * Return an object with all the keys in the object that have a falsy value removed.
@@ -18559,20 +18566,21 @@ const HLOOKUP = {
18559
18566
  description: _t("Horizontal lookup"),
18560
18567
  args: [
18561
18568
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18562
- 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.")),
18569
+ 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.")),
18563
18570
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18564
18571
  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.")),
18565
18572
  ],
18566
18573
  returns: ["ANY"],
18567
18574
  computeValueAndFormat: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18568
18575
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18569
- assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18576
+ const _range = toMatrix(range);
18577
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18570
18578
  const getValueFromRange = (range, index) => range[index][0].value;
18571
18579
  const _isSorted = toBoolean(isSorted.value);
18572
18580
  const colIndex = _isSorted
18573
- ? dichotomicSearch(range, searchKey?.value, "nextSmaller", "asc", range.length, getValueFromRange)
18574
- : linearSearch(range, searchKey?.value, "strict", range.length, getValueFromRange);
18575
- const col = range[colIndex];
18581
+ ? dichotomicSearch(_range, searchKey?.value, "nextSmaller", "asc", _range.length, getValueFromRange)
18582
+ : linearSearch(_range, searchKey?.value, "strict", _range.length, getValueFromRange);
18583
+ const col = _range[colIndex];
18576
18584
  assertAvailable(col, searchKey?.value);
18577
18585
  return col[_index - 1];
18578
18586
  },
@@ -18617,36 +18625,38 @@ const LOOKUP = {
18617
18625
  description: _t("Look up a value."),
18618
18626
  args: [
18619
18627
  arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18620
- 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.")),
18621
- 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.")),
18628
+ 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.")),
18629
+ 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.")),
18622
18630
  ],
18623
18631
  returns: ["ANY"],
18624
18632
  computeValueAndFormat: function (searchKey, searchArray, resultRange) {
18625
- let nbCol = searchArray.length;
18626
- let nbRow = searchArray[0].length;
18633
+ const _searchArray = toMatrix(searchArray);
18634
+ const _resultRange = toMatrix(resultRange);
18635
+ let nbCol = _searchArray.length;
18636
+ let nbRow = _searchArray[0].length;
18627
18637
  const verticalSearch = nbRow >= nbCol;
18628
18638
  const getElement = verticalSearch
18629
18639
  ? (range, index) => range[0][index].value
18630
18640
  : (range, index) => range[index][0].value;
18631
18641
  const rangeLength = verticalSearch ? nbRow : nbCol;
18632
- const index = dichotomicSearch(searchArray, searchKey?.value, "nextSmaller", "asc", rangeLength, getElement);
18642
+ const index = dichotomicSearch(_searchArray, searchKey?.value, "nextSmaller", "asc", rangeLength, getElement);
18633
18643
  if (index === -1)
18634
18644
  assertAvailable(undefined, searchKey?.value);
18635
18645
  verticalSearch
18636
- ? assertAvailable(searchArray[0][index], searchKey?.value)
18637
- : assertAvailable(searchArray[index][nbRow - 1], searchKey?.value);
18638
- if (resultRange === undefined) {
18639
- return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
18646
+ ? assertAvailable(_searchArray[0][index], searchKey?.value)
18647
+ : assertAvailable(_searchArray[index][nbRow - 1], searchKey?.value);
18648
+ if (_resultRange[0].length === 0) {
18649
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
18640
18650
  }
18641
- nbCol = resultRange.length;
18642
- nbRow = resultRange[0].length;
18651
+ nbCol = _resultRange.length;
18652
+ nbRow = _resultRange[0].length;
18643
18653
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
18644
18654
  if (nbCol > 1) {
18645
18655
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
18646
- return resultRange[index][0];
18656
+ return _resultRange[index][0];
18647
18657
  }
18648
18658
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
18649
- return resultRange[0][index];
18659
+ return _resultRange[0][index];
18650
18660
  },
18651
18661
  isExported: true,
18652
18662
  };
@@ -18664,27 +18674,28 @@ const MATCH = {
18664
18674
  returns: ["NUMBER"],
18665
18675
  compute: function (searchKey, range, searchType = DEFAULT_SEARCH_TYPE) {
18666
18676
  let _searchType = toNumber(searchType, this.locale);
18667
- const nbCol = range.length;
18668
- const nbRow = range[0].length;
18677
+ const _range = toMatrix(range);
18678
+ const nbCol = _range.length;
18679
+ const nbRow = _range[0].length;
18669
18680
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
18670
18681
  let index = -1;
18671
18682
  const getElement = nbCol === 1
18672
- ? (range, index) => range[0][index]
18673
- : (range, index) => range[index][0];
18674
- const rangeLen = nbCol === 1 ? range[0].length : range.length;
18683
+ ? (_range, index) => _range[0][index]
18684
+ : (_range, index) => _range[index][0];
18685
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
18675
18686
  _searchType = Math.sign(_searchType);
18676
18687
  switch (_searchType) {
18677
18688
  case 1:
18678
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18689
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18679
18690
  break;
18680
18691
  case 0:
18681
- index = linearSearch(range, searchKey, "strict", rangeLen, getElement);
18692
+ index = linearSearch(_range, searchKey, "strict", rangeLen, getElement);
18682
18693
  break;
18683
18694
  case -1:
18684
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18695
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18685
18696
  break;
18686
18697
  }
18687
- assertAvailable(nbCol === 1 ? range[0][index] : range[index], searchKey);
18698
+ assertAvailable(nbCol === 1 ? _range[0][index] : _range[index], searchKey);
18688
18699
  return index + 1;
18689
18700
  },
18690
18701
  isExported: true,
@@ -18733,13 +18744,14 @@ const VLOOKUP = {
18733
18744
  returns: ["ANY"],
18734
18745
  computeValueAndFormat: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18735
18746
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18736
- assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18747
+ const _range = toMatrix(range);
18748
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18737
18749
  const getValueFromRange = (range, index) => range[0][index].value;
18738
18750
  const _isSorted = toBoolean(isSorted.value);
18739
18751
  const rowIndex = _isSorted
18740
- ? dichotomicSearch(range, searchKey?.value, "nextSmaller", "asc", range[0].length, getValueFromRange)
18741
- : linearSearch(range, searchKey?.value, "strict", range[0].length, getValueFromRange);
18742
- const value = range[_index - 1][rowIndex];
18752
+ ? dichotomicSearch(_range, searchKey?.value, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18753
+ : linearSearch(_range, searchKey?.value, "strict", _range[0].length, getValueFromRange);
18754
+ const value = _range[_index - 1][rowIndex];
18743
18755
  assertAvailable(value, searchKey?.value);
18744
18756
  return value;
18745
18757
  },
@@ -18766,26 +18778,28 @@ const XLOOKUP = {
18766
18778
  computeValueAndFormat: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18767
18779
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18768
18780
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
18769
- assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18781
+ const _lookupRange = toMatrix(lookupRange);
18782
+ const _returnRange = toMatrix(returnRange);
18783
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18770
18784
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("searchMode should be a value in [-1, 1, -2, 2]."));
18771
18785
  assert(() => [-1, 0, 1].includes(_matchMode), _t("matchMode should be a value in [-1, 0, 1]."));
18772
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
18786
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
18773
18787
  assert(() => lookupDirection === "col"
18774
- ? returnRange[0].length === lookupRange[0].length
18775
- : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18788
+ ? _returnRange[0].length === _lookupRange[0].length
18789
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18776
18790
  const getElement = lookupDirection === "col"
18777
18791
  ? (range, index) => range[0][index].value
18778
18792
  : (range, index) => range[index][0].value;
18779
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
18793
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
18780
18794
  const mode = _matchMode === 0 ? "strict" : _matchMode === 1 ? "nextGreater" : "nextSmaller";
18781
18795
  const reverseSearch = _searchMode === -1;
18782
18796
  const index = _searchMode === 2 || _searchMode === -2
18783
- ? dichotomicSearch(lookupRange, searchKey?.value, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18784
- : linearSearch(lookupRange, searchKey?.value, mode, rangeLen, getElement, reverseSearch);
18797
+ ? dichotomicSearch(_lookupRange, searchKey?.value, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18798
+ : linearSearch(_lookupRange, searchKey?.value, mode, rangeLen, getElement, reverseSearch);
18785
18799
  if (index !== -1) {
18786
18800
  return lookupDirection === "col"
18787
- ? returnRange.map((col) => [col[index]])
18788
- : [returnRange[index]];
18801
+ ? _returnRange.map((col) => [col[index]])
18802
+ : [_returnRange[index]];
18789
18803
  }
18790
18804
  const _defaultValue = defaultValue?.();
18791
18805
  assertAvailable(_defaultValue, searchKey?.value);
@@ -29243,6 +29257,9 @@ function useGridDrawing(refName, model, canvasSize) {
29243
29257
  canvas.width = width * dpr;
29244
29258
  canvas.height = height * dpr;
29245
29259
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
29260
+ if (width === 0 || height === 0) {
29261
+ return;
29262
+ }
29246
29263
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
29247
29264
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
29248
29265
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -34723,7 +34740,7 @@ class BordersPlugin extends CorePlugin {
34723
34740
  getCommonSides(border1, border2) {
34724
34741
  const commonBorder = {};
34725
34742
  for (let side of ["top", "bottom", "left", "right"]) {
34726
- if (border1[side] && border1[side] === border2[side]) {
34743
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
34727
34744
  commonBorder[side] = border1[side];
34728
34745
  }
34729
34746
  }
@@ -46269,11 +46286,10 @@ class RendererPlugin extends UIPlugin {
46269
46286
  switch (layer) {
46270
46287
  case 0 /* LAYERS.Background */:
46271
46288
  this.drawGlobalBackground(renderingContext);
46272
- for (const zone of this.getters.getAllActiveViewportsZones()) {
46289
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
46273
46290
  const { ctx } = renderingContext;
46274
46291
  ctx.save();
46275
46292
  ctx.beginPath();
46276
- const rect = this.getters.getVisibleRect(zone);
46277
46293
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
46278
46294
  ctx.clip();
46279
46295
  this.boxes = this.getGridBoxes(zone);
@@ -46543,10 +46559,8 @@ class RendererPlugin extends UIPlugin {
46543
46559
  const { ctx, thinLineWidth } = renderingContext;
46544
46560
  const visibleCols = this.getters.getSheetViewVisibleCols();
46545
46561
  const left = visibleCols[0];
46546
- const right = visibleCols[visibleCols.length - 1];
46547
46562
  const visibleRows = this.getters.getSheetViewVisibleRows();
46548
46563
  const top = visibleRows[0];
46549
- const bottom = visibleRows[visibleRows.length - 1];
46550
46564
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
46551
46565
  const selection = this.getters.getSelectedZones();
46552
46566
  const selectedCols = getZonesCols(selection);
@@ -46562,7 +46576,7 @@ class RendererPlugin extends UIPlugin {
46562
46576
  ctx.lineWidth = thinLineWidth;
46563
46577
  ctx.strokeStyle = "#333";
46564
46578
  // Columns headers background
46565
- for (let col = left; col <= right; col++) {
46579
+ for (const col of visibleCols) {
46566
46580
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
46567
46581
  const { x, width } = this.getters.getVisibleRect(colZone);
46568
46582
  const colHasFilter = this.getters.doesZonesContainFilter(sheetId, [colZone]);
@@ -46582,7 +46596,7 @@ class RendererPlugin extends UIPlugin {
46582
46596
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
46583
46597
  }
46584
46598
  // Rows headers background
46585
- for (let row = top; row <= bottom; row++) {
46599
+ for (const row of visibleRows) {
46586
46600
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
46587
46601
  const { y, height } = this.getters.getVisibleRect(rowZone);
46588
46602
  const rowHasFilter = this.getters.doesZonesContainFilter(sheetId, [rowZone]);
@@ -46611,21 +46625,21 @@ class RendererPlugin extends UIPlugin {
46611
46625
  ctx.stroke();
46612
46626
  ctx.beginPath();
46613
46627
  // column text + separator
46614
- for (const i of visibleCols) {
46615
- const colSize = this.getters.getColSize(sheetId, i);
46616
- const colName = numberToLetters(i);
46617
- ctx.fillStyle = activeCols.has(i) ? "#fff" : TEXT_HEADER_COLOR;
46618
- let colStart = this.getHeaderOffset("COL", left, i);
46628
+ for (const col of visibleCols) {
46629
+ const colSize = this.getters.getColSize(sheetId, col);
46630
+ const colName = numberToLetters(col);
46631
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
46632
+ let colStart = this.getHeaderOffset("COL", left, col);
46619
46633
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
46620
46634
  ctx.moveTo(colStart + colSize, 0);
46621
46635
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
46622
46636
  }
46623
46637
  // row text + separator
46624
- for (const i of visibleRows) {
46625
- const rowSize = this.getters.getRowSize(sheetId, i);
46626
- ctx.fillStyle = activeRows.has(i) ? "#fff" : TEXT_HEADER_COLOR;
46627
- let rowStart = this.getHeaderOffset("ROW", top, i);
46628
- ctx.fillText(String(i + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
46638
+ for (const row of visibleRows) {
46639
+ const rowSize = this.getters.getRowSize(sheetId, row);
46640
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
46641
+ let rowStart = this.getHeaderOffset("ROW", top, row);
46642
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
46629
46643
  ctx.moveTo(0, rowStart + rowSize);
46630
46644
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
46631
46645
  }
@@ -50516,8 +50530,17 @@ class InternalViewport {
50516
50530
  this.getters = getters;
50517
50531
  this.sheetId = sheetId;
50518
50532
  this.boundaries = boundaries;
50519
- this.viewportWidth = sizeInGrid.width;
50520
- this.viewportHeight = sizeInGrid.height;
50533
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
50534
+ throw new Error("Viewport size cannot be negative");
50535
+ }
50536
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
50537
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
50538
+ this.top = boundaries.top;
50539
+ this.bottom = boundaries.bottom;
50540
+ this.left = boundaries.left;
50541
+ this.right = boundaries.right;
50542
+ this.offsetX = offsets.x;
50543
+ this.offsetY = offsets.y;
50521
50544
  this.offsetScrollbarX = offsets.x;
50522
50545
  this.offsetScrollbarY = offsets.y;
50523
50546
  this.canScrollVertically = options.canScrollVertically;
@@ -50560,9 +50583,9 @@ class InternalViewport {
50560
50583
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
50561
50584
  );
50562
50585
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
50563
- }
50564
- if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
50565
- height += FOOTER_HEIGHT;
50586
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
50587
+ height += FOOTER_HEIGHT;
50588
+ }
50566
50589
  }
50567
50590
  return { width, height };
50568
50591
  }
@@ -50709,6 +50732,9 @@ class InternalViewport {
50709
50732
  }
50710
50733
  // PRIVATE
50711
50734
  searchHeaderIndex(dimension, position, startIndex = 0) {
50735
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
50736
+ return -1;
50737
+ }
50712
50738
  const sheetId = this.sheetId;
50713
50739
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
50714
50740
  // using a binary search:
@@ -50748,7 +50774,7 @@ class InternalViewport {
50748
50774
  this.adjustViewportZoneY();
50749
50775
  }
50750
50776
  /** Corrects the viewport's horizontal offset based on the current structure
50751
- * To make sure that at least on column is visible inside the viewport.
50777
+ * To make sure that at least one column is visible inside the viewport.
50752
50778
  */
50753
50779
  adjustViewportOffsetX() {
50754
50780
  if (this.canScrollHorizontally) {
@@ -50765,7 +50791,7 @@ class InternalViewport {
50765
50791
  this.adjustViewportZoneX();
50766
50792
  }
50767
50793
  /** Corrects the viewport's vertical offset based on the current structure
50768
- * To make sure that at least on row is visible inside the viewport.
50794
+ * To make sure that at least one row is visible inside the viewport.
50769
50795
  */
50770
50796
  adjustViewportOffsetY() {
50771
50797
  if (this.canScrollVertically) {
@@ -50787,11 +50813,14 @@ class InternalViewport {
50787
50813
  const sheetId = this.sheetId;
50788
50814
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
50789
50815
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
50816
+ if (!this.viewportWidth) {
50817
+ return;
50818
+ }
50790
50819
  if (this.left === -1) {
50791
50820
  this.left = this.boundaries.left;
50792
50821
  }
50793
50822
  if (this.right === -1) {
50794
- this.right = this.getters.getNumberCols(sheetId) - 1;
50823
+ this.right = this.boundaries.right;
50795
50824
  }
50796
50825
  this.offsetX =
50797
50826
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -50803,11 +50832,14 @@ class InternalViewport {
50803
50832
  const sheetId = this.sheetId;
50804
50833
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
50805
50834
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
50835
+ if (!this.viewportHeight) {
50836
+ return;
50837
+ }
50806
50838
  if (this.top === -1) {
50807
50839
  this.top = this.boundaries.top;
50808
50840
  }
50809
50841
  if (this.bottom === -1) {
50810
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
50842
+ this.bottom = this.boundaries.bottom;
50811
50843
  }
50812
50844
  this.offsetY =
50813
50845
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -50879,7 +50911,7 @@ class SheetViewPlugin extends UIPlugin {
50879
50911
  "getSheetViewVisibleRows",
50880
50912
  "getFrozenSheetViewRatio",
50881
50913
  "isPositionVisible",
50882
- "getAllActiveViewportsZones",
50914
+ "getAllActiveViewportsZonesAndRect",
50883
50915
  "getRect",
50884
50916
  ];
50885
50917
  viewports = {};
@@ -51113,12 +51145,12 @@ class SheetViewPlugin extends UIPlugin {
51113
51145
  const sheetId = this.getters.getActiveSheetId();
51114
51146
  const viewports = this.getSubViewports(sheetId);
51115
51147
  //TODO ake another commit to eimprove this
51116
- return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
51148
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
51117
51149
  }
51118
51150
  getSheetViewVisibleRows() {
51119
51151
  const sheetId = this.getters.getActiveSheetId();
51120
51152
  const viewports = this.getSubViewports(sheetId);
51121
- return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
51153
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
51122
51154
  }
51123
51155
  /**
51124
51156
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -51161,19 +51193,19 @@ class SheetViewPlugin extends UIPlugin {
51161
51193
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
51162
51194
  };
51163
51195
  }
51164
- getColRowOffsetInViewport(dimension, referenceIndex, index) {
51165
- const sheetId = this.getters.getActiveSheetId();
51166
- const visibleCols = this.getters.getSheetViewVisibleCols();
51167
- const visibleRows = this.getters.getSheetViewVisibleRows();
51168
- if (index < referenceIndex) {
51169
- return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
51196
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
51197
+ if (targetHeaderIndex < referenceHeaderIndex) {
51198
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
51170
51199
  }
51200
+ const sheetId = this.getters.getActiveSheetId();
51201
+ const visibleHeaders = dimension === "COL"
51202
+ ? this.getters.getSheetViewVisibleCols()
51203
+ : this.getters.getSheetViewVisibleRows();
51204
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
51205
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
51206
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
51171
51207
  let offset = 0;
51172
- const visibleIndexes = dimension === "COL" ? visibleCols : visibleRows;
51173
- for (let i = referenceIndex; i < index; i++) {
51174
- if (!visibleIndexes.includes(i)) {
51175
- continue;
51176
- }
51208
+ for (const i of relevantIndexes) {
51177
51209
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
51178
51210
  }
51179
51211
  return offset;
@@ -51220,7 +51252,7 @@ class SheetViewPlugin extends UIPlugin {
51220
51252
  }
51221
51253
  return { canEdgeScroll, direction, delay };
51222
51254
  }
51223
- getEdgeScrollRow(y, previousY, tartingY) {
51255
+ getEdgeScrollRow(y, previousY, startingY) {
51224
51256
  let canEdgeScroll = false;
51225
51257
  let direction = 0;
51226
51258
  let delay = 0;
@@ -51241,7 +51273,7 @@ class SheetViewPlugin extends UIPlugin {
51241
51273
  delay = scrollDelay(y - height);
51242
51274
  direction = 1;
51243
51275
  }
51244
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
51276
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
51245
51277
  // 2
51246
51278
  canEdgeScroll = true;
51247
51279
  delay = scrollDelay(offsetCorrectionY - y);
@@ -51267,13 +51299,7 @@ class SheetViewPlugin extends UIPlugin {
51267
51299
  */
51268
51300
  getVisibleRectWithoutHeaders(zone) {
51269
51301
  const sheetId = this.getters.getActiveSheetId();
51270
- const viewportRects = this.getSubViewports(sheetId)
51271
- .map((viewport) => viewport.getVisibleRect(zone))
51272
- .filter(isDefined$1);
51273
- if (viewportRects.length === 0) {
51274
- return { x: 0, y: 0, width: 0, height: 0 };
51275
- }
51276
- return this.recomposeRect(viewportRects);
51302
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
51277
51303
  }
51278
51304
  /**
51279
51305
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -51281,13 +51307,7 @@ class SheetViewPlugin extends UIPlugin {
51281
51307
  */
51282
51308
  getRect(zone) {
51283
51309
  const sheetId = this.getters.getActiveSheetId();
51284
- const viewportRects = this.getSubViewports(sheetId)
51285
- .map((viewport) => viewport.getFullRect(zone))
51286
- .filter(isDefined$1);
51287
- if (viewportRects.length === 0) {
51288
- return { x: 0, y: 0, width: 0, height: 0 };
51289
- }
51290
- const rect = this.recomposeRect(viewportRects);
51310
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
51291
51311
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
51292
51312
  }
51293
51313
  /**
@@ -51302,9 +51322,18 @@ class SheetViewPlugin extends UIPlugin {
51302
51322
  const y = this.getters.getRowDimensions(sheetId, ySplit).start;
51303
51323
  return { x, y };
51304
51324
  }
51305
- getAllActiveViewportsZones() {
51325
+ getAllActiveViewportsZonesAndRect() {
51306
51326
  const sheetId = this.getters.getActiveSheetId();
51307
- return this.getSubViewports(sheetId);
51327
+ return this.getSubViewports(sheetId).map((viewport) => {
51328
+ return {
51329
+ zone: viewport,
51330
+ rect: {
51331
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
51332
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
51333
+ ...viewport.getMaxSize(),
51334
+ },
51335
+ };
51336
+ });
51308
51337
  }
51309
51338
  // ---------------------------------------------------------------------------
51310
51339
  // Private
@@ -51357,12 +51386,11 @@ class SheetViewPlugin extends UIPlugin {
51357
51386
  }
51358
51387
  /** gets rid of deprecated sheetIds */
51359
51388
  cleanViewports() {
51360
- const sheetIds = this.getters.getSheetIds();
51361
- for (let sheetId of Object.keys(this.viewports)) {
51362
- if (!sheetIds.includes(sheetId)) {
51363
- delete this.viewports[sheetId];
51364
- }
51389
+ const newViewport = {};
51390
+ for (const sheetId of this.getters.getSheetIds()) {
51391
+ newViewport[sheetId] = this.viewports[sheetId];
51365
51392
  }
51393
+ this.viewports = newViewport;
51366
51394
  }
51367
51395
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
51368
51396
  this.sheetViewHeight = height;
@@ -51372,14 +51400,14 @@ class SheetViewPlugin extends UIPlugin {
51372
51400
  this.recomputeViewports();
51373
51401
  }
51374
51402
  recomputeViewports() {
51375
- for (let sheetId of Object.keys(this.viewports)) {
51403
+ for (const sheetId of this.getters.getSheetIds()) {
51376
51404
  this.resetViewports(sheetId);
51377
51405
  }
51378
51406
  }
51379
51407
  setSheetViewOffset(offsetX, offsetY) {
51380
51408
  const sheetId = this.getters.getActiveSheetId();
51381
51409
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
51382
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
51410
+ this.getSubViewports(sheetId).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
51383
51411
  }
51384
51412
  getViewportOffset(sheetId) {
51385
51413
  return {
@@ -51394,8 +51422,10 @@ class SheetViewPlugin extends UIPlugin {
51394
51422
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
51395
51423
  const nCols = this.getters.getNumberCols(sheetId);
51396
51424
  const nRows = this.getters.getNumberRows(sheetId);
51397
- const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
51398
- const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
51425
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
51426
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
51427
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
51428
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
51399
51429
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
51400
51430
  const canScrollHorizontally = xRatio < 1.0;
51401
51431
  const canScrollVertically = yRatio < 1.0;
@@ -51406,14 +51436,14 @@ class SheetViewPlugin extends UIPlugin {
51406
51436
  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 })) ||
51407
51437
  undefined,
51408
51438
  topRight: (ySplit &&
51409
- 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 })) ||
51439
+ 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 })) ||
51410
51440
  undefined,
51411
51441
  bottomLeft: (xSplit &&
51412
- 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 })) ||
51442
+ 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 })) ||
51413
51443
  undefined,
51414
51444
  bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
51415
- width: this.sheetViewWidth - colOffset,
51416
- height: this.sheetViewHeight - rowOffset,
51445
+ width: unfrozenWidth,
51446
+ height: unfrozenHeight,
51417
51447
  }, { canScrollHorizontally, canScrollVertically }, {
51418
51448
  x: canScrollHorizontally ? previousOffset.x : 0,
51419
51449
  y: canScrollVertically ? previousOffset.y : 0,
@@ -51425,7 +51455,7 @@ class SheetViewPlugin extends UIPlugin {
51425
51455
  * Adjust the viewport such that the anchor position is visible
51426
51456
  */
51427
51457
  refreshViewport(sheetId, anchorPosition) {
51428
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => {
51458
+ this.getSubViewports(sheetId).forEach((viewport) => {
51429
51459
  viewport.adjustViewportZone();
51430
51460
  viewport.adjustPosition(anchorPosition);
51431
51461
  });
@@ -51490,12 +51520,26 @@ class SheetViewPlugin extends UIPlugin {
51490
51520
  const height = this.sheetViewHeight + this.gridOffsetY;
51491
51521
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
51492
51522
  }
51493
- recomposeRect(viewportRects) {
51494
- const x = Math.min(...viewportRects.map((rect) => rect.x));
51495
- const y = Math.min(...viewportRects.map((rect) => rect.y));
51496
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
51497
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
51498
- return { x, y, width, height };
51523
+ mapViewportsToRect(sheetId, rectCallBack) {
51524
+ let x = Infinity;
51525
+ let y = Infinity;
51526
+ let width = 0;
51527
+ let height = 0;
51528
+ let hasViewports = false;
51529
+ for (const viewport of this.getSubViewports(sheetId)) {
51530
+ const rect = rectCallBack(viewport);
51531
+ if (rect) {
51532
+ hasViewports = true;
51533
+ x = Math.min(x, rect.x);
51534
+ y = Math.min(y, rect.y);
51535
+ width = Math.max(width, rect.x + rect.width);
51536
+ height = Math.max(height, rect.y + rect.height);
51537
+ }
51538
+ }
51539
+ if (!hasViewports) {
51540
+ return { x: 0, y: 0, width: 0, height: 0 };
51541
+ }
51542
+ return { x, y, width: width - x, height: height - y };
51499
51543
  }
51500
51544
  }
51501
51545
 
@@ -57804,6 +57848,6 @@ exports.setTranslationMethod = setTranslationMethod;
57804
57848
  exports.tokenize = tokenize;
57805
57849
 
57806
57850
 
57807
- __info__.version = "17.0.47";
57808
- __info__.date = "2025-01-31T07:56:50.980Z";
57809
- __info__.hash = "a22bce2";
57851
+ __info__.version = "17.0.49";
57852
+ __info__.date = "2025-02-10T08:55:47.771Z";
57853
+ __info__.hash = "1049319";