@odoo/o-spreadsheet 17.0.47 → 17.0.48

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.48
6
+ * @date 2025-02-05T07:18:39.331Z
7
+ * @hash aea9101
8
8
  */
9
9
 
10
10
  'use strict';
@@ -18559,20 +18559,21 @@ const HLOOKUP = {
18559
18559
  description: _t("Horizontal lookup"),
18560
18560
  args: [
18561
18561
  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.")),
18562
+ 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
18563
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18564
18564
  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
18565
  ],
18566
18566
  returns: ["ANY"],
18567
18567
  computeValueAndFormat: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18568
18568
  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."));
18569
+ const _range = toMatrix(range);
18570
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18570
18571
  const getValueFromRange = (range, index) => range[index][0].value;
18571
18572
  const _isSorted = toBoolean(isSorted.value);
18572
18573
  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];
18574
+ ? dichotomicSearch(_range, searchKey?.value, "nextSmaller", "asc", _range.length, getValueFromRange)
18575
+ : linearSearch(_range, searchKey?.value, "strict", _range.length, getValueFromRange);
18576
+ const col = _range[colIndex];
18576
18577
  assertAvailable(col, searchKey?.value);
18577
18578
  return col[_index - 1];
18578
18579
  },
@@ -18617,36 +18618,38 @@ const LOOKUP = {
18617
18618
  description: _t("Look up a value."),
18618
18619
  args: [
18619
18620
  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.")),
18621
+ 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.")),
18622
+ 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
18623
  ],
18623
18624
  returns: ["ANY"],
18624
18625
  computeValueAndFormat: function (searchKey, searchArray, resultRange) {
18625
- let nbCol = searchArray.length;
18626
- let nbRow = searchArray[0].length;
18626
+ const _searchArray = toMatrix(searchArray);
18627
+ const _resultRange = toMatrix(resultRange);
18628
+ let nbCol = _searchArray.length;
18629
+ let nbRow = _searchArray[0].length;
18627
18630
  const verticalSearch = nbRow >= nbCol;
18628
18631
  const getElement = verticalSearch
18629
18632
  ? (range, index) => range[0][index].value
18630
18633
  : (range, index) => range[index][0].value;
18631
18634
  const rangeLength = verticalSearch ? nbRow : nbCol;
18632
- const index = dichotomicSearch(searchArray, searchKey?.value, "nextSmaller", "asc", rangeLength, getElement);
18635
+ const index = dichotomicSearch(_searchArray, searchKey?.value, "nextSmaller", "asc", rangeLength, getElement);
18633
18636
  if (index === -1)
18634
18637
  assertAvailable(undefined, searchKey?.value);
18635
18638
  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];
18639
+ ? assertAvailable(_searchArray[0][index], searchKey?.value)
18640
+ : assertAvailable(_searchArray[index][nbRow - 1], searchKey?.value);
18641
+ if (_resultRange[0].length === 0) {
18642
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
18640
18643
  }
18641
- nbCol = resultRange.length;
18642
- nbRow = resultRange[0].length;
18644
+ nbCol = _resultRange.length;
18645
+ nbRow = _resultRange[0].length;
18643
18646
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
18644
18647
  if (nbCol > 1) {
18645
18648
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
18646
- return resultRange[index][0];
18649
+ return _resultRange[index][0];
18647
18650
  }
18648
18651
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
18649
- return resultRange[0][index];
18652
+ return _resultRange[0][index];
18650
18653
  },
18651
18654
  isExported: true,
18652
18655
  };
@@ -18664,27 +18667,28 @@ const MATCH = {
18664
18667
  returns: ["NUMBER"],
18665
18668
  compute: function (searchKey, range, searchType = DEFAULT_SEARCH_TYPE) {
18666
18669
  let _searchType = toNumber(searchType, this.locale);
18667
- const nbCol = range.length;
18668
- const nbRow = range[0].length;
18670
+ const _range = toMatrix(range);
18671
+ const nbCol = _range.length;
18672
+ const nbRow = _range[0].length;
18669
18673
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
18670
18674
  let index = -1;
18671
18675
  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;
18676
+ ? (_range, index) => _range[0][index]
18677
+ : (_range, index) => _range[index][0];
18678
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
18675
18679
  _searchType = Math.sign(_searchType);
18676
18680
  switch (_searchType) {
18677
18681
  case 1:
18678
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18682
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18679
18683
  break;
18680
18684
  case 0:
18681
- index = linearSearch(range, searchKey, "strict", rangeLen, getElement);
18685
+ index = linearSearch(_range, searchKey, "strict", rangeLen, getElement);
18682
18686
  break;
18683
18687
  case -1:
18684
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18688
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18685
18689
  break;
18686
18690
  }
18687
- assertAvailable(nbCol === 1 ? range[0][index] : range[index], searchKey);
18691
+ assertAvailable(nbCol === 1 ? _range[0][index] : _range[index], searchKey);
18688
18692
  return index + 1;
18689
18693
  },
18690
18694
  isExported: true,
@@ -18733,13 +18737,14 @@ const VLOOKUP = {
18733
18737
  returns: ["ANY"],
18734
18738
  computeValueAndFormat: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18735
18739
  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."));
18740
+ const _range = toMatrix(range);
18741
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18737
18742
  const getValueFromRange = (range, index) => range[0][index].value;
18738
18743
  const _isSorted = toBoolean(isSorted.value);
18739
18744
  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];
18745
+ ? dichotomicSearch(_range, searchKey?.value, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18746
+ : linearSearch(_range, searchKey?.value, "strict", _range[0].length, getValueFromRange);
18747
+ const value = _range[_index - 1][rowIndex];
18743
18748
  assertAvailable(value, searchKey?.value);
18744
18749
  return value;
18745
18750
  },
@@ -18766,26 +18771,28 @@ const XLOOKUP = {
18766
18771
  computeValueAndFormat: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18767
18772
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18768
18773
  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."));
18774
+ const _lookupRange = toMatrix(lookupRange);
18775
+ const _returnRange = toMatrix(returnRange);
18776
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18770
18777
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("searchMode should be a value in [-1, 1, -2, 2]."));
18771
18778
  assert(() => [-1, 0, 1].includes(_matchMode), _t("matchMode should be a value in [-1, 0, 1]."));
18772
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
18779
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
18773
18780
  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."));
18781
+ ? _returnRange[0].length === _lookupRange[0].length
18782
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18776
18783
  const getElement = lookupDirection === "col"
18777
18784
  ? (range, index) => range[0][index].value
18778
18785
  : (range, index) => range[index][0].value;
18779
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
18786
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
18780
18787
  const mode = _matchMode === 0 ? "strict" : _matchMode === 1 ? "nextGreater" : "nextSmaller";
18781
18788
  const reverseSearch = _searchMode === -1;
18782
18789
  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);
18790
+ ? dichotomicSearch(_lookupRange, searchKey?.value, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18791
+ : linearSearch(_lookupRange, searchKey?.value, mode, rangeLen, getElement, reverseSearch);
18785
18792
  if (index !== -1) {
18786
18793
  return lookupDirection === "col"
18787
- ? returnRange.map((col) => [col[index]])
18788
- : [returnRange[index]];
18794
+ ? _returnRange.map((col) => [col[index]])
18795
+ : [_returnRange[index]];
18789
18796
  }
18790
18797
  const _defaultValue = defaultValue?.();
18791
18798
  assertAvailable(_defaultValue, searchKey?.value);
@@ -29243,6 +29250,9 @@ function useGridDrawing(refName, model, canvasSize) {
29243
29250
  canvas.width = width * dpr;
29244
29251
  canvas.height = height * dpr;
29245
29252
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
29253
+ if (width === 0 || height === 0) {
29254
+ return;
29255
+ }
29246
29256
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
29247
29257
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
29248
29258
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -34723,7 +34733,7 @@ class BordersPlugin extends CorePlugin {
34723
34733
  getCommonSides(border1, border2) {
34724
34734
  const commonBorder = {};
34725
34735
  for (let side of ["top", "bottom", "left", "right"]) {
34726
- if (border1[side] && border1[side] === border2[side]) {
34736
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
34727
34737
  commonBorder[side] = border1[side];
34728
34738
  }
34729
34739
  }
@@ -46269,11 +46279,10 @@ class RendererPlugin extends UIPlugin {
46269
46279
  switch (layer) {
46270
46280
  case 0 /* LAYERS.Background */:
46271
46281
  this.drawGlobalBackground(renderingContext);
46272
- for (const zone of this.getters.getAllActiveViewportsZones()) {
46282
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
46273
46283
  const { ctx } = renderingContext;
46274
46284
  ctx.save();
46275
46285
  ctx.beginPath();
46276
- const rect = this.getters.getVisibleRect(zone);
46277
46286
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
46278
46287
  ctx.clip();
46279
46288
  this.boxes = this.getGridBoxes(zone);
@@ -46543,10 +46552,8 @@ class RendererPlugin extends UIPlugin {
46543
46552
  const { ctx, thinLineWidth } = renderingContext;
46544
46553
  const visibleCols = this.getters.getSheetViewVisibleCols();
46545
46554
  const left = visibleCols[0];
46546
- const right = visibleCols[visibleCols.length - 1];
46547
46555
  const visibleRows = this.getters.getSheetViewVisibleRows();
46548
46556
  const top = visibleRows[0];
46549
- const bottom = visibleRows[visibleRows.length - 1];
46550
46557
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
46551
46558
  const selection = this.getters.getSelectedZones();
46552
46559
  const selectedCols = getZonesCols(selection);
@@ -46562,7 +46569,7 @@ class RendererPlugin extends UIPlugin {
46562
46569
  ctx.lineWidth = thinLineWidth;
46563
46570
  ctx.strokeStyle = "#333";
46564
46571
  // Columns headers background
46565
- for (let col = left; col <= right; col++) {
46572
+ for (const col of visibleCols) {
46566
46573
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
46567
46574
  const { x, width } = this.getters.getVisibleRect(colZone);
46568
46575
  const colHasFilter = this.getters.doesZonesContainFilter(sheetId, [colZone]);
@@ -46582,7 +46589,7 @@ class RendererPlugin extends UIPlugin {
46582
46589
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
46583
46590
  }
46584
46591
  // Rows headers background
46585
- for (let row = top; row <= bottom; row++) {
46592
+ for (const row of visibleRows) {
46586
46593
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
46587
46594
  const { y, height } = this.getters.getVisibleRect(rowZone);
46588
46595
  const rowHasFilter = this.getters.doesZonesContainFilter(sheetId, [rowZone]);
@@ -46611,21 +46618,21 @@ class RendererPlugin extends UIPlugin {
46611
46618
  ctx.stroke();
46612
46619
  ctx.beginPath();
46613
46620
  // 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);
46621
+ for (const col of visibleCols) {
46622
+ const colSize = this.getters.getColSize(sheetId, col);
46623
+ const colName = numberToLetters(col);
46624
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
46625
+ let colStart = this.getHeaderOffset("COL", left, col);
46619
46626
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
46620
46627
  ctx.moveTo(colStart + colSize, 0);
46621
46628
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
46622
46629
  }
46623
46630
  // 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);
46631
+ for (const row of visibleRows) {
46632
+ const rowSize = this.getters.getRowSize(sheetId, row);
46633
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
46634
+ let rowStart = this.getHeaderOffset("ROW", top, row);
46635
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
46629
46636
  ctx.moveTo(0, rowStart + rowSize);
46630
46637
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
46631
46638
  }
@@ -50516,8 +50523,17 @@ class InternalViewport {
50516
50523
  this.getters = getters;
50517
50524
  this.sheetId = sheetId;
50518
50525
  this.boundaries = boundaries;
50519
- this.viewportWidth = sizeInGrid.width;
50520
- this.viewportHeight = sizeInGrid.height;
50526
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
50527
+ throw new Error("Viewport size cannot be negative");
50528
+ }
50529
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
50530
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
50531
+ this.top = boundaries.top;
50532
+ this.bottom = boundaries.bottom;
50533
+ this.left = boundaries.left;
50534
+ this.right = boundaries.right;
50535
+ this.offsetX = offsets.x;
50536
+ this.offsetY = offsets.y;
50521
50537
  this.offsetScrollbarX = offsets.x;
50522
50538
  this.offsetScrollbarY = offsets.y;
50523
50539
  this.canScrollVertically = options.canScrollVertically;
@@ -50560,9 +50576,9 @@ class InternalViewport {
50560
50576
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
50561
50577
  );
50562
50578
  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;
50579
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
50580
+ height += FOOTER_HEIGHT;
50581
+ }
50566
50582
  }
50567
50583
  return { width, height };
50568
50584
  }
@@ -50709,6 +50725,9 @@ class InternalViewport {
50709
50725
  }
50710
50726
  // PRIVATE
50711
50727
  searchHeaderIndex(dimension, position, startIndex = 0) {
50728
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
50729
+ return -1;
50730
+ }
50712
50731
  const sheetId = this.sheetId;
50713
50732
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
50714
50733
  // using a binary search:
@@ -50748,7 +50767,7 @@ class InternalViewport {
50748
50767
  this.adjustViewportZoneY();
50749
50768
  }
50750
50769
  /** 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.
50770
+ * To make sure that at least one column is visible inside the viewport.
50752
50771
  */
50753
50772
  adjustViewportOffsetX() {
50754
50773
  if (this.canScrollHorizontally) {
@@ -50765,7 +50784,7 @@ class InternalViewport {
50765
50784
  this.adjustViewportZoneX();
50766
50785
  }
50767
50786
  /** 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.
50787
+ * To make sure that at least one row is visible inside the viewport.
50769
50788
  */
50770
50789
  adjustViewportOffsetY() {
50771
50790
  if (this.canScrollVertically) {
@@ -50787,11 +50806,14 @@ class InternalViewport {
50787
50806
  const sheetId = this.sheetId;
50788
50807
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
50789
50808
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
50809
+ if (!this.viewportWidth) {
50810
+ return;
50811
+ }
50790
50812
  if (this.left === -1) {
50791
50813
  this.left = this.boundaries.left;
50792
50814
  }
50793
50815
  if (this.right === -1) {
50794
- this.right = this.getters.getNumberCols(sheetId) - 1;
50816
+ this.right = this.boundaries.right;
50795
50817
  }
50796
50818
  this.offsetX =
50797
50819
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -50803,11 +50825,14 @@ class InternalViewport {
50803
50825
  const sheetId = this.sheetId;
50804
50826
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
50805
50827
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
50828
+ if (!this.viewportHeight) {
50829
+ return;
50830
+ }
50806
50831
  if (this.top === -1) {
50807
50832
  this.top = this.boundaries.top;
50808
50833
  }
50809
50834
  if (this.bottom === -1) {
50810
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
50835
+ this.bottom = this.boundaries.bottom;
50811
50836
  }
50812
50837
  this.offsetY =
50813
50838
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -50879,7 +50904,7 @@ class SheetViewPlugin extends UIPlugin {
50879
50904
  "getSheetViewVisibleRows",
50880
50905
  "getFrozenSheetViewRatio",
50881
50906
  "isPositionVisible",
50882
- "getAllActiveViewportsZones",
50907
+ "getAllActiveViewportsZonesAndRect",
50883
50908
  "getRect",
50884
50909
  ];
50885
50910
  viewports = {};
@@ -51113,12 +51138,12 @@ class SheetViewPlugin extends UIPlugin {
51113
51138
  const sheetId = this.getters.getActiveSheetId();
51114
51139
  const viewports = this.getSubViewports(sheetId);
51115
51140
  //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));
51141
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
51117
51142
  }
51118
51143
  getSheetViewVisibleRows() {
51119
51144
  const sheetId = this.getters.getActiveSheetId();
51120
51145
  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));
51146
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
51122
51147
  }
51123
51148
  /**
51124
51149
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -51161,19 +51186,19 @@ class SheetViewPlugin extends UIPlugin {
51161
51186
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
51162
51187
  };
51163
51188
  }
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);
51189
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
51190
+ if (targetHeaderIndex < referenceHeaderIndex) {
51191
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
51170
51192
  }
51193
+ const sheetId = this.getters.getActiveSheetId();
51194
+ const visibleHeaders = dimension === "COL"
51195
+ ? this.getters.getSheetViewVisibleCols()
51196
+ : this.getters.getSheetViewVisibleRows();
51197
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
51198
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
51199
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
51171
51200
  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
- }
51201
+ for (const i of relevantIndexes) {
51177
51202
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
51178
51203
  }
51179
51204
  return offset;
@@ -51220,7 +51245,7 @@ class SheetViewPlugin extends UIPlugin {
51220
51245
  }
51221
51246
  return { canEdgeScroll, direction, delay };
51222
51247
  }
51223
- getEdgeScrollRow(y, previousY, tartingY) {
51248
+ getEdgeScrollRow(y, previousY, startingY) {
51224
51249
  let canEdgeScroll = false;
51225
51250
  let direction = 0;
51226
51251
  let delay = 0;
@@ -51241,7 +51266,7 @@ class SheetViewPlugin extends UIPlugin {
51241
51266
  delay = scrollDelay(y - height);
51242
51267
  direction = 1;
51243
51268
  }
51244
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
51269
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
51245
51270
  // 2
51246
51271
  canEdgeScroll = true;
51247
51272
  delay = scrollDelay(offsetCorrectionY - y);
@@ -51267,13 +51292,7 @@ class SheetViewPlugin extends UIPlugin {
51267
51292
  */
51268
51293
  getVisibleRectWithoutHeaders(zone) {
51269
51294
  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);
51295
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
51277
51296
  }
51278
51297
  /**
51279
51298
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -51281,13 +51300,7 @@ class SheetViewPlugin extends UIPlugin {
51281
51300
  */
51282
51301
  getRect(zone) {
51283
51302
  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);
51303
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
51291
51304
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
51292
51305
  }
51293
51306
  /**
@@ -51302,9 +51315,18 @@ class SheetViewPlugin extends UIPlugin {
51302
51315
  const y = this.getters.getRowDimensions(sheetId, ySplit).start;
51303
51316
  return { x, y };
51304
51317
  }
51305
- getAllActiveViewportsZones() {
51318
+ getAllActiveViewportsZonesAndRect() {
51306
51319
  const sheetId = this.getters.getActiveSheetId();
51307
- return this.getSubViewports(sheetId);
51320
+ return this.getSubViewports(sheetId).map((viewport) => {
51321
+ return {
51322
+ zone: viewport,
51323
+ rect: {
51324
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
51325
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
51326
+ ...viewport.getMaxSize(),
51327
+ },
51328
+ };
51329
+ });
51308
51330
  }
51309
51331
  // ---------------------------------------------------------------------------
51310
51332
  // Private
@@ -51357,12 +51379,11 @@ class SheetViewPlugin extends UIPlugin {
51357
51379
  }
51358
51380
  /** gets rid of deprecated sheetIds */
51359
51381
  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
- }
51382
+ const newViewport = {};
51383
+ for (const sheetId of this.getters.getSheetIds()) {
51384
+ newViewport[sheetId] = this.viewports[sheetId];
51365
51385
  }
51386
+ this.viewports = newViewport;
51366
51387
  }
51367
51388
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
51368
51389
  this.sheetViewHeight = height;
@@ -51372,14 +51393,14 @@ class SheetViewPlugin extends UIPlugin {
51372
51393
  this.recomputeViewports();
51373
51394
  }
51374
51395
  recomputeViewports() {
51375
- for (let sheetId of Object.keys(this.viewports)) {
51396
+ for (const sheetId of this.getters.getSheetIds()) {
51376
51397
  this.resetViewports(sheetId);
51377
51398
  }
51378
51399
  }
51379
51400
  setSheetViewOffset(offsetX, offsetY) {
51380
51401
  const sheetId = this.getters.getActiveSheetId();
51381
51402
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
51382
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
51403
+ this.getSubViewports(sheetId).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
51383
51404
  }
51384
51405
  getViewportOffset(sheetId) {
51385
51406
  return {
@@ -51394,8 +51415,10 @@ class SheetViewPlugin extends UIPlugin {
51394
51415
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
51395
51416
  const nCols = this.getters.getNumberCols(sheetId);
51396
51417
  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);
51418
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
51419
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
51420
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
51421
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
51399
51422
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
51400
51423
  const canScrollHorizontally = xRatio < 1.0;
51401
51424
  const canScrollVertically = yRatio < 1.0;
@@ -51406,14 +51429,14 @@ class SheetViewPlugin extends UIPlugin {
51406
51429
  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
51430
  undefined,
51408
51431
  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 })) ||
51432
+ 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
51433
  undefined,
51411
51434
  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 })) ||
51435
+ 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
51436
  undefined,
51414
51437
  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,
51438
+ width: unfrozenWidth,
51439
+ height: unfrozenHeight,
51417
51440
  }, { canScrollHorizontally, canScrollVertically }, {
51418
51441
  x: canScrollHorizontally ? previousOffset.x : 0,
51419
51442
  y: canScrollVertically ? previousOffset.y : 0,
@@ -51425,7 +51448,7 @@ class SheetViewPlugin extends UIPlugin {
51425
51448
  * Adjust the viewport such that the anchor position is visible
51426
51449
  */
51427
51450
  refreshViewport(sheetId, anchorPosition) {
51428
- Object.values(this.getSubViewports(sheetId)).forEach((viewport) => {
51451
+ this.getSubViewports(sheetId).forEach((viewport) => {
51429
51452
  viewport.adjustViewportZone();
51430
51453
  viewport.adjustPosition(anchorPosition);
51431
51454
  });
@@ -51490,12 +51513,26 @@ class SheetViewPlugin extends UIPlugin {
51490
51513
  const height = this.sheetViewHeight + this.gridOffsetY;
51491
51514
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
51492
51515
  }
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 };
51516
+ mapViewportsToRect(sheetId, rectCallBack) {
51517
+ let x = Infinity;
51518
+ let y = Infinity;
51519
+ let width = 0;
51520
+ let height = 0;
51521
+ let hasViewports = false;
51522
+ for (const viewport of this.getSubViewports(sheetId)) {
51523
+ const rect = rectCallBack(viewport);
51524
+ if (rect) {
51525
+ hasViewports = true;
51526
+ x = Math.min(x, rect.x);
51527
+ y = Math.min(y, rect.y);
51528
+ width = Math.max(width, rect.x + rect.width);
51529
+ height = Math.max(height, rect.y + rect.height);
51530
+ }
51531
+ }
51532
+ if (!hasViewports) {
51533
+ return { x: 0, y: 0, width: 0, height: 0 };
51534
+ }
51535
+ return { x, y, width: width - x, height: height - y };
51499
51536
  }
51500
51537
  }
51501
51538
 
@@ -57804,6 +57841,6 @@ exports.setTranslationMethod = setTranslationMethod;
57804
57841
  exports.tokenize = tokenize;
57805
57842
 
57806
57843
 
57807
- __info__.version = "17.0.47";
57808
- __info__.date = "2025-01-31T07:56:50.980Z";
57809
- __info__.hash = "a22bce2";
57844
+ __info__.version = "17.0.48";
57845
+ __info__.date = "2025-02-05T07:18:39.331Z";
57846
+ __info__.hash = "aea9101";