@odoo/o-spreadsheet 17.2.34 → 17.2.36
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.
- package/dist/o-spreadsheet.cjs.js +171 -127
- package/dist/o-spreadsheet.d.ts +11 -14
- package/dist/o-spreadsheet.esm.js +171 -127
- package/dist/o-spreadsheet.iife.js +171 -127
- package/dist/o-spreadsheet.iife.min.js +4 -4
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.2.
|
|
7
|
-
* @date 2025-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.2.36
|
|
7
|
+
* @date 2025-02-10T08:59:25.719Z
|
|
8
|
+
* @hash 5a942bd
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -606,9 +606,16 @@ function deepEquals(o1, o2) {
|
|
|
606
606
|
}
|
|
607
607
|
return true;
|
|
608
608
|
}
|
|
609
|
-
/**
|
|
609
|
+
/**
|
|
610
|
+
* Check if the given array contains all the values of the other array.
|
|
611
|
+
* It makes the assumption that both array do not contain duplicates.
|
|
612
|
+
*/
|
|
610
613
|
function includesAll(arr, values) {
|
|
611
|
-
|
|
614
|
+
if (arr.length < values.length) {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
const set = new Set(arr);
|
|
618
|
+
return values.every((value) => set.has(value));
|
|
612
619
|
}
|
|
613
620
|
/**
|
|
614
621
|
* Return an object with all the keys in the object that have a falsy value removed.
|
|
@@ -17753,23 +17760,24 @@ const HLOOKUP = {
|
|
|
17753
17760
|
description: _t("Horizontal lookup"),
|
|
17754
17761
|
args: [
|
|
17755
17762
|
arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
17756
|
-
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.")),
|
|
17763
|
+
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.")),
|
|
17757
17764
|
arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
|
|
17758
17765
|
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.")),
|
|
17759
17766
|
],
|
|
17760
17767
|
returns: ["ANY"],
|
|
17761
17768
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
17762
17769
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
17763
|
-
|
|
17770
|
+
const _range = toMatrix(range);
|
|
17771
|
+
assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
17764
17772
|
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
17765
17773
|
return searchKey;
|
|
17766
17774
|
}
|
|
17767
17775
|
const getValueFromRange = (range, index) => range[index][0].value;
|
|
17768
17776
|
const _isSorted = toBoolean(isSorted.value);
|
|
17769
17777
|
const colIndex = _isSorted
|
|
17770
|
-
? dichotomicSearch(
|
|
17771
|
-
: linearSearch(
|
|
17772
|
-
const col =
|
|
17778
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
17779
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
17780
|
+
const col = _range[colIndex];
|
|
17773
17781
|
if (col === undefined) {
|
|
17774
17782
|
return valueNotAvailable(searchKey);
|
|
17775
17783
|
}
|
|
@@ -17878,36 +17886,38 @@ const LOOKUP = {
|
|
|
17878
17886
|
description: _t("Look up a value."),
|
|
17879
17887
|
args: [
|
|
17880
17888
|
arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
17881
|
-
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.")),
|
|
17882
|
-
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.")),
|
|
17889
|
+
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.")),
|
|
17890
|
+
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.")),
|
|
17883
17891
|
],
|
|
17884
17892
|
returns: ["ANY"],
|
|
17885
17893
|
compute: function (searchKey, searchArray, resultRange) {
|
|
17886
|
-
|
|
17887
|
-
|
|
17894
|
+
const _searchArray = toMatrix(searchArray);
|
|
17895
|
+
const _resultRange = toMatrix(resultRange);
|
|
17896
|
+
let nbCol = _searchArray.length;
|
|
17897
|
+
let nbRow = _searchArray[0].length;
|
|
17888
17898
|
const verticalSearch = nbRow >= nbCol;
|
|
17889
17899
|
const getElement = verticalSearch
|
|
17890
17900
|
? (range, index) => range[0][index].value
|
|
17891
17901
|
: (range, index) => range[index][0].value;
|
|
17892
17902
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
17893
|
-
const index = dichotomicSearch(
|
|
17903
|
+
const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
17894
17904
|
if (index === -1 ||
|
|
17895
|
-
(verticalSearch &&
|
|
17896
|
-
(!verticalSearch &&
|
|
17905
|
+
(verticalSearch && _searchArray[0][index] === undefined) ||
|
|
17906
|
+
(!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
|
|
17897
17907
|
return valueNotAvailable(searchKey);
|
|
17898
17908
|
}
|
|
17899
|
-
if (
|
|
17900
|
-
return verticalSearch ?
|
|
17909
|
+
if (_resultRange[0].length === 0) {
|
|
17910
|
+
return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
|
|
17901
17911
|
}
|
|
17902
|
-
nbCol =
|
|
17903
|
-
nbRow =
|
|
17912
|
+
nbCol = _resultRange.length;
|
|
17913
|
+
nbRow = _resultRange[0].length;
|
|
17904
17914
|
assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
|
|
17905
17915
|
if (nbCol > 1) {
|
|
17906
17916
|
assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
|
|
17907
|
-
return
|
|
17917
|
+
return _resultRange[index][0];
|
|
17908
17918
|
}
|
|
17909
17919
|
assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
|
|
17910
|
-
return
|
|
17920
|
+
return _resultRange[0][index];
|
|
17911
17921
|
},
|
|
17912
17922
|
isExported: true,
|
|
17913
17923
|
};
|
|
@@ -17925,28 +17935,29 @@ const MATCH = {
|
|
|
17925
17935
|
returns: ["NUMBER"],
|
|
17926
17936
|
compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
|
|
17927
17937
|
let _searchType = toNumber(searchType, this.locale);
|
|
17928
|
-
const
|
|
17929
|
-
const
|
|
17938
|
+
const _range = toMatrix(range);
|
|
17939
|
+
const nbCol = _range.length;
|
|
17940
|
+
const nbRow = _range[0].length;
|
|
17930
17941
|
assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
|
|
17931
17942
|
let index = -1;
|
|
17932
17943
|
const getElement = nbCol === 1
|
|
17933
|
-
? (
|
|
17934
|
-
: (
|
|
17935
|
-
const rangeLen = nbCol === 1 ?
|
|
17944
|
+
? (_range, index) => _range[0][index].value
|
|
17945
|
+
: (_range, index) => _range[index][0].value;
|
|
17946
|
+
const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
|
|
17936
17947
|
_searchType = Math.sign(_searchType);
|
|
17937
17948
|
switch (_searchType) {
|
|
17938
17949
|
case 1:
|
|
17939
|
-
index = dichotomicSearch(
|
|
17950
|
+
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
17940
17951
|
break;
|
|
17941
17952
|
case 0:
|
|
17942
|
-
index = linearSearch(
|
|
17953
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
17943
17954
|
break;
|
|
17944
17955
|
case -1:
|
|
17945
|
-
index = dichotomicSearch(
|
|
17956
|
+
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
17946
17957
|
break;
|
|
17947
17958
|
}
|
|
17948
|
-
if ((nbCol === 1 &&
|
|
17949
|
-
(nbCol !== 1 &&
|
|
17959
|
+
if ((nbCol === 1 && _range[0][index] === undefined) ||
|
|
17960
|
+
(nbCol !== 1 && _range[index] === undefined)) {
|
|
17950
17961
|
return valueNotAvailable(searchKey);
|
|
17951
17962
|
}
|
|
17952
17963
|
return index + 1;
|
|
@@ -17997,16 +18008,17 @@ const VLOOKUP = {
|
|
|
17997
18008
|
returns: ["ANY"],
|
|
17998
18009
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
17999
18010
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18000
|
-
|
|
18011
|
+
const _range = toMatrix(range);
|
|
18012
|
+
assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18001
18013
|
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
18002
18014
|
return searchKey;
|
|
18003
18015
|
}
|
|
18004
18016
|
const getValueFromRange = (range, index) => range[0][index].value;
|
|
18005
18017
|
const _isSorted = toBoolean(isSorted.value);
|
|
18006
18018
|
const rowIndex = _isSorted
|
|
18007
|
-
? dichotomicSearch(
|
|
18008
|
-
: linearSearch(
|
|
18009
|
-
const value =
|
|
18019
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18020
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18021
|
+
const value = _range[_index - 1][rowIndex];
|
|
18010
18022
|
if (value === undefined) {
|
|
18011
18023
|
return valueNotAvailable(searchKey);
|
|
18012
18024
|
}
|
|
@@ -18044,30 +18056,32 @@ const XLOOKUP = {
|
|
|
18044
18056
|
compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
|
|
18045
18057
|
const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
|
|
18046
18058
|
const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
|
|
18047
|
-
|
|
18059
|
+
const _lookupRange = toMatrix(lookupRange);
|
|
18060
|
+
const _returnRange = toMatrix(returnRange);
|
|
18061
|
+
assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
|
|
18048
18062
|
assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
|
|
18049
18063
|
assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
|
|
18050
|
-
const lookupDirection =
|
|
18064
|
+
const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
|
|
18051
18065
|
assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
|
|
18052
18066
|
assert(() => lookupDirection === "col"
|
|
18053
|
-
?
|
|
18054
|
-
:
|
|
18067
|
+
? _returnRange[0].length === _lookupRange[0].length
|
|
18068
|
+
: _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
|
|
18055
18069
|
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
18056
18070
|
return [[searchKey]];
|
|
18057
18071
|
}
|
|
18058
18072
|
const getElement = lookupDirection === "col"
|
|
18059
18073
|
? (range, index) => range[0][index].value
|
|
18060
18074
|
: (range, index) => range[index][0].value;
|
|
18061
|
-
const rangeLen = lookupDirection === "col" ?
|
|
18075
|
+
const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
|
|
18062
18076
|
const mode = MATCH_MODE[_matchMode];
|
|
18063
18077
|
const reverseSearch = _searchMode === -1;
|
|
18064
18078
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18065
|
-
? dichotomicSearch(
|
|
18066
|
-
: linearSearch(
|
|
18079
|
+
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18080
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
18067
18081
|
if (index !== -1) {
|
|
18068
18082
|
return lookupDirection === "col"
|
|
18069
|
-
?
|
|
18070
|
-
: [
|
|
18083
|
+
? _returnRange.map((col) => [col[index]])
|
|
18084
|
+
: [_returnRange[index]];
|
|
18071
18085
|
}
|
|
18072
18086
|
if (defaultValue === undefined) {
|
|
18073
18087
|
return valueNotAvailable(searchKey);
|
|
@@ -34697,11 +34711,10 @@ class GridRenderer {
|
|
|
34697
34711
|
switch (layer) {
|
|
34698
34712
|
case "Background":
|
|
34699
34713
|
this.drawGlobalBackground(renderingContext);
|
|
34700
|
-
for (const zone of this.getters.
|
|
34714
|
+
for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
|
|
34701
34715
|
const { ctx } = renderingContext;
|
|
34702
34716
|
ctx.save();
|
|
34703
34717
|
ctx.beginPath();
|
|
34704
|
-
const rect = this.getters.getVisibleRect(zone);
|
|
34705
34718
|
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
34706
34719
|
ctx.clip();
|
|
34707
34720
|
const boxes = this.getGridBoxes(zone);
|
|
@@ -34971,10 +34984,8 @@ class GridRenderer {
|
|
|
34971
34984
|
const { ctx, thinLineWidth } = renderingContext;
|
|
34972
34985
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
34973
34986
|
const left = visibleCols[0];
|
|
34974
|
-
const right = visibleCols[visibleCols.length - 1];
|
|
34975
34987
|
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
34976
34988
|
const top = visibleRows[0];
|
|
34977
|
-
const bottom = visibleRows[visibleRows.length - 1];
|
|
34978
34989
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
34979
34990
|
const selection = this.getters.getSelectedZones();
|
|
34980
34991
|
const selectedCols = getZonesCols(selection);
|
|
@@ -34990,7 +35001,7 @@ class GridRenderer {
|
|
|
34990
35001
|
ctx.lineWidth = thinLineWidth;
|
|
34991
35002
|
ctx.strokeStyle = "#333";
|
|
34992
35003
|
// Columns headers background
|
|
34993
|
-
for (
|
|
35004
|
+
for (const col of visibleCols) {
|
|
34994
35005
|
const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
|
|
34995
35006
|
const { x, width } = this.getters.getVisibleRect(colZone);
|
|
34996
35007
|
const isColActive = activeCols.has(col);
|
|
@@ -35007,7 +35018,7 @@ class GridRenderer {
|
|
|
35007
35018
|
ctx.fillRect(x, 0, width, HEADER_HEIGHT);
|
|
35008
35019
|
}
|
|
35009
35020
|
// Rows headers background
|
|
35010
|
-
for (
|
|
35021
|
+
for (const row of visibleRows) {
|
|
35011
35022
|
const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
|
|
35012
35023
|
const { y, height } = this.getters.getVisibleRect(rowZone);
|
|
35013
35024
|
const isRowActive = activeRows.has(row);
|
|
@@ -35033,21 +35044,21 @@ class GridRenderer {
|
|
|
35033
35044
|
ctx.stroke();
|
|
35034
35045
|
ctx.beginPath();
|
|
35035
35046
|
// column text + separator
|
|
35036
|
-
for (const
|
|
35037
|
-
const colSize = this.getters.getColSize(sheetId,
|
|
35038
|
-
const colName = numberToLetters(
|
|
35039
|
-
ctx.fillStyle = activeCols.has(
|
|
35040
|
-
let colStart = this.getHeaderOffset("COL", left,
|
|
35047
|
+
for (const col of visibleCols) {
|
|
35048
|
+
const colSize = this.getters.getColSize(sheetId, col);
|
|
35049
|
+
const colName = numberToLetters(col);
|
|
35050
|
+
ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
|
|
35051
|
+
let colStart = this.getHeaderOffset("COL", left, col);
|
|
35041
35052
|
ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
|
|
35042
35053
|
ctx.moveTo(colStart + colSize, 0);
|
|
35043
35054
|
ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
|
|
35044
35055
|
}
|
|
35045
35056
|
// row text + separator
|
|
35046
|
-
for (const
|
|
35047
|
-
const rowSize = this.getters.getRowSize(sheetId,
|
|
35048
|
-
ctx.fillStyle = activeRows.has(
|
|
35049
|
-
let rowStart = this.getHeaderOffset("ROW", top,
|
|
35050
|
-
ctx.fillText(String(
|
|
35057
|
+
for (const row of visibleRows) {
|
|
35058
|
+
const rowSize = this.getters.getRowSize(sheetId, row);
|
|
35059
|
+
ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
|
|
35060
|
+
let rowStart = this.getHeaderOffset("ROW", top, row);
|
|
35061
|
+
ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
|
|
35051
35062
|
ctx.moveTo(0, rowStart + rowSize);
|
|
35052
35063
|
ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
|
|
35053
35064
|
}
|
|
@@ -35339,6 +35350,9 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
35339
35350
|
canvas.width = width * dpr;
|
|
35340
35351
|
canvas.height = height * dpr;
|
|
35341
35352
|
canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
|
|
35353
|
+
if (width === 0 || height === 0) {
|
|
35354
|
+
return;
|
|
35355
|
+
}
|
|
35342
35356
|
// Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
|
|
35343
35357
|
// are the edges of the squares. If you draw a one-unit-wide line between whole-number
|
|
35344
35358
|
// coordinates, it will overlap opposite sides of the pixel square, and the resulting
|
|
@@ -40896,7 +40910,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
40896
40910
|
getCommonSides(border1, border2) {
|
|
40897
40911
|
const commonBorder = {};
|
|
40898
40912
|
for (let side of ["top", "bottom", "left", "right"]) {
|
|
40899
|
-
if (border1[side] && border1[side]
|
|
40913
|
+
if (border1[side] && deepEquals(border1[side], border2[side])) {
|
|
40900
40914
|
commonBorder[side] = border1[side];
|
|
40901
40915
|
}
|
|
40902
40916
|
}
|
|
@@ -53807,8 +53821,17 @@ class InternalViewport {
|
|
|
53807
53821
|
this.getters = getters;
|
|
53808
53822
|
this.sheetId = sheetId;
|
|
53809
53823
|
this.boundaries = boundaries;
|
|
53810
|
-
|
|
53811
|
-
|
|
53824
|
+
if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
|
|
53825
|
+
throw new Error("Viewport size cannot be negative");
|
|
53826
|
+
}
|
|
53827
|
+
this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
|
|
53828
|
+
this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
|
|
53829
|
+
this.top = boundaries.top;
|
|
53830
|
+
this.bottom = boundaries.bottom;
|
|
53831
|
+
this.left = boundaries.left;
|
|
53832
|
+
this.right = boundaries.right;
|
|
53833
|
+
this.offsetX = offsets.x;
|
|
53834
|
+
this.offsetY = offsets.y;
|
|
53812
53835
|
this.offsetScrollbarX = offsets.x;
|
|
53813
53836
|
this.offsetScrollbarY = offsets.y;
|
|
53814
53837
|
this.canScrollVertically = options.canScrollVertically;
|
|
@@ -53851,9 +53874,9 @@ class InternalViewport {
|
|
|
53851
53874
|
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
53852
53875
|
);
|
|
53853
53876
|
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
53854
|
-
|
|
53855
|
-
|
|
53856
|
-
|
|
53877
|
+
if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
|
|
53878
|
+
height += FOOTER_HEIGHT;
|
|
53879
|
+
}
|
|
53857
53880
|
}
|
|
53858
53881
|
return { width, height };
|
|
53859
53882
|
}
|
|
@@ -53990,6 +54013,9 @@ class InternalViewport {
|
|
|
53990
54013
|
!this.getters.isRowHidden(this.sheetId, row));
|
|
53991
54014
|
}
|
|
53992
54015
|
searchHeaderIndex(dimension, position, startIndex = 0) {
|
|
54016
|
+
if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
|
|
54017
|
+
return -1;
|
|
54018
|
+
}
|
|
53993
54019
|
const sheetId = this.sheetId;
|
|
53994
54020
|
const headers = this.getters.getNumberHeaders(sheetId, dimension);
|
|
53995
54021
|
// using a binary search:
|
|
@@ -54026,7 +54052,7 @@ class InternalViewport {
|
|
|
54026
54052
|
this.adjustViewportZoneY();
|
|
54027
54053
|
}
|
|
54028
54054
|
/** Corrects the viewport's horizontal offset based on the current structure
|
|
54029
|
-
* To make sure that at least
|
|
54055
|
+
* To make sure that at least one column is visible inside the viewport.
|
|
54030
54056
|
*/
|
|
54031
54057
|
adjustViewportOffsetX() {
|
|
54032
54058
|
if (this.canScrollHorizontally) {
|
|
@@ -54038,7 +54064,7 @@ class InternalViewport {
|
|
|
54038
54064
|
this.adjustViewportZoneX();
|
|
54039
54065
|
}
|
|
54040
54066
|
/** Corrects the viewport's vertical offset based on the current structure
|
|
54041
|
-
* To make sure that at least
|
|
54067
|
+
* To make sure that at least one row is visible inside the viewport.
|
|
54042
54068
|
*/
|
|
54043
54069
|
adjustViewportOffsetY() {
|
|
54044
54070
|
if (this.canScrollVertically) {
|
|
@@ -54055,11 +54081,14 @@ class InternalViewport {
|
|
|
54055
54081
|
const sheetId = this.sheetId;
|
|
54056
54082
|
this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
|
|
54057
54083
|
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
|
|
54084
|
+
if (!this.viewportWidth) {
|
|
54085
|
+
return;
|
|
54086
|
+
}
|
|
54058
54087
|
if (this.left === -1) {
|
|
54059
54088
|
this.left = this.boundaries.left;
|
|
54060
54089
|
}
|
|
54061
54090
|
if (this.right === -1) {
|
|
54062
|
-
this.right = this.
|
|
54091
|
+
this.right = this.boundaries.right;
|
|
54063
54092
|
}
|
|
54064
54093
|
this.offsetX =
|
|
54065
54094
|
this.getters.getColDimensions(sheetId, this.left).start -
|
|
@@ -54071,11 +54100,14 @@ class InternalViewport {
|
|
|
54071
54100
|
const sheetId = this.sheetId;
|
|
54072
54101
|
this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
|
|
54073
54102
|
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
|
|
54103
|
+
if (!this.viewportHeight) {
|
|
54104
|
+
return;
|
|
54105
|
+
}
|
|
54074
54106
|
if (this.top === -1) {
|
|
54075
54107
|
this.top = this.boundaries.top;
|
|
54076
54108
|
}
|
|
54077
54109
|
if (this.bottom === -1) {
|
|
54078
|
-
this.bottom = this.
|
|
54110
|
+
this.bottom = this.boundaries.bottom;
|
|
54079
54111
|
}
|
|
54080
54112
|
this.offsetY =
|
|
54081
54113
|
this.getters.getRowDimensions(sheetId, this.top).start -
|
|
@@ -54149,7 +54181,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54149
54181
|
"isPositionVisible",
|
|
54150
54182
|
"getColDimensionsInViewport",
|
|
54151
54183
|
"getRowDimensionsInViewport",
|
|
54152
|
-
"
|
|
54184
|
+
"getAllActiveViewportsZonesAndRect",
|
|
54153
54185
|
"getRect",
|
|
54154
54186
|
];
|
|
54155
54187
|
viewports = {};
|
|
@@ -54383,12 +54415,12 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54383
54415
|
const sheetId = this.getters.getActiveSheetId();
|
|
54384
54416
|
const viewports = this.getSubViewports(sheetId);
|
|
54385
54417
|
//TODO ake another commit to eimprove this
|
|
54386
|
-
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
54418
|
+
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
54387
54419
|
}
|
|
54388
54420
|
getSheetViewVisibleRows() {
|
|
54389
54421
|
const sheetId = this.getters.getActiveSheetId();
|
|
54390
54422
|
const viewports = this.getSubViewports(sheetId);
|
|
54391
|
-
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
54423
|
+
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
54392
54424
|
}
|
|
54393
54425
|
/**
|
|
54394
54426
|
* Get the positions of all the cells that are visible in the viewport, taking merges into account.
|
|
@@ -54431,19 +54463,19 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54431
54463
|
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
54432
54464
|
};
|
|
54433
54465
|
}
|
|
54434
|
-
getColRowOffsetInViewport(dimension,
|
|
54435
|
-
|
|
54436
|
-
|
|
54437
|
-
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
54438
|
-
if (index < referenceIndex) {
|
|
54439
|
-
return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
|
|
54466
|
+
getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
|
|
54467
|
+
if (targetHeaderIndex < referenceHeaderIndex) {
|
|
54468
|
+
return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
|
|
54440
54469
|
}
|
|
54470
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
54471
|
+
const visibleHeaders = dimension === "COL"
|
|
54472
|
+
? this.getters.getSheetViewVisibleCols()
|
|
54473
|
+
: this.getters.getSheetViewVisibleRows();
|
|
54474
|
+
const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
|
|
54475
|
+
const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
|
|
54476
|
+
const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
|
|
54441
54477
|
let offset = 0;
|
|
54442
|
-
const
|
|
54443
|
-
for (let i = referenceIndex; i < index; i++) {
|
|
54444
|
-
if (!visibleIndexes.includes(i)) {
|
|
54445
|
-
continue;
|
|
54446
|
-
}
|
|
54478
|
+
for (const i of relevantIndexes) {
|
|
54447
54479
|
offset += this.getters.getHeaderSize(sheetId, dimension, i);
|
|
54448
54480
|
}
|
|
54449
54481
|
return offset;
|
|
@@ -54490,7 +54522,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54490
54522
|
}
|
|
54491
54523
|
return { canEdgeScroll, direction, delay };
|
|
54492
54524
|
}
|
|
54493
|
-
getEdgeScrollRow(y, previousY,
|
|
54525
|
+
getEdgeScrollRow(y, previousY, startingY) {
|
|
54494
54526
|
let canEdgeScroll = false;
|
|
54495
54527
|
let direction = 0;
|
|
54496
54528
|
let delay = 0;
|
|
@@ -54511,7 +54543,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54511
54543
|
delay = scrollDelay(y - height);
|
|
54512
54544
|
direction = 1;
|
|
54513
54545
|
}
|
|
54514
|
-
else if (y < offsetCorrectionY &&
|
|
54546
|
+
else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
|
|
54515
54547
|
// 2
|
|
54516
54548
|
canEdgeScroll = true;
|
|
54517
54549
|
delay = scrollDelay(offsetCorrectionY - y);
|
|
@@ -54537,13 +54569,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54537
54569
|
*/
|
|
54538
54570
|
getVisibleRectWithoutHeaders(zone) {
|
|
54539
54571
|
const sheetId = this.getters.getActiveSheetId();
|
|
54540
|
-
|
|
54541
|
-
.map((viewport) => viewport.getVisibleRect(zone))
|
|
54542
|
-
.filter(isDefined$1);
|
|
54543
|
-
if (viewportRects.length === 0) {
|
|
54544
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
54545
|
-
}
|
|
54546
|
-
return this.recomposeRect(viewportRects);
|
|
54572
|
+
return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
|
|
54547
54573
|
}
|
|
54548
54574
|
/**
|
|
54549
54575
|
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
@@ -54551,13 +54577,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54551
54577
|
*/
|
|
54552
54578
|
getRect(zone) {
|
|
54553
54579
|
const sheetId = this.getters.getActiveSheetId();
|
|
54554
|
-
const
|
|
54555
|
-
.map((viewport) => viewport.getFullRect(zone))
|
|
54556
|
-
.filter(isDefined$1);
|
|
54557
|
-
if (viewportRects.length === 0) {
|
|
54558
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
54559
|
-
}
|
|
54560
|
-
const rect = this.recomposeRect(viewportRects);
|
|
54580
|
+
const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
|
|
54561
54581
|
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
54562
54582
|
}
|
|
54563
54583
|
/**
|
|
@@ -54602,9 +54622,18 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54602
54622
|
end: start + (isRowHidden ? 0 : size),
|
|
54603
54623
|
};
|
|
54604
54624
|
}
|
|
54605
|
-
|
|
54625
|
+
getAllActiveViewportsZonesAndRect() {
|
|
54606
54626
|
const sheetId = this.getters.getActiveSheetId();
|
|
54607
|
-
return this.getSubViewports(sheetId)
|
|
54627
|
+
return this.getSubViewports(sheetId).map((viewport) => {
|
|
54628
|
+
return {
|
|
54629
|
+
zone: viewport,
|
|
54630
|
+
rect: {
|
|
54631
|
+
x: viewport.offsetCorrectionX + this.gridOffsetX,
|
|
54632
|
+
y: viewport.offsetCorrectionY + this.gridOffsetY,
|
|
54633
|
+
...viewport.getMaxSize(),
|
|
54634
|
+
},
|
|
54635
|
+
};
|
|
54636
|
+
});
|
|
54608
54637
|
}
|
|
54609
54638
|
// ---------------------------------------------------------------------------
|
|
54610
54639
|
// Private
|
|
@@ -54657,12 +54686,11 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54657
54686
|
}
|
|
54658
54687
|
/** gets rid of deprecated sheetIds */
|
|
54659
54688
|
cleanViewports() {
|
|
54660
|
-
const
|
|
54661
|
-
for (
|
|
54662
|
-
|
|
54663
|
-
delete this.viewports[sheetId];
|
|
54664
|
-
}
|
|
54689
|
+
const newViewport = {};
|
|
54690
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
54691
|
+
newViewport[sheetId] = this.viewports[sheetId];
|
|
54665
54692
|
}
|
|
54693
|
+
this.viewports = newViewport;
|
|
54666
54694
|
}
|
|
54667
54695
|
resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
|
|
54668
54696
|
this.sheetViewHeight = height;
|
|
@@ -54672,14 +54700,14 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54672
54700
|
this.recomputeViewports();
|
|
54673
54701
|
}
|
|
54674
54702
|
recomputeViewports() {
|
|
54675
|
-
for (
|
|
54703
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
54676
54704
|
this.resetViewports(sheetId);
|
|
54677
54705
|
}
|
|
54678
54706
|
}
|
|
54679
54707
|
setSheetViewOffset(offsetX, offsetY) {
|
|
54680
54708
|
const sheetId = this.getters.getActiveSheetId();
|
|
54681
54709
|
const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
|
|
54682
|
-
|
|
54710
|
+
this.getSubViewports(sheetId).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
|
|
54683
54711
|
}
|
|
54684
54712
|
getViewportOffset(sheetId) {
|
|
54685
54713
|
return {
|
|
@@ -54694,8 +54722,10 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54694
54722
|
const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
|
|
54695
54723
|
const nCols = this.getters.getNumberCols(sheetId);
|
|
54696
54724
|
const nRows = this.getters.getNumberRows(sheetId);
|
|
54697
|
-
const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
|
|
54698
|
-
const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
|
|
54725
|
+
const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
|
|
54726
|
+
const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
|
|
54727
|
+
const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
|
|
54728
|
+
const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
|
|
54699
54729
|
const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
|
|
54700
54730
|
const canScrollHorizontally = xRatio < 1.0;
|
|
54701
54731
|
const canScrollVertically = yRatio < 1.0;
|
|
@@ -54706,14 +54736,14 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54706
54736
|
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 })) ||
|
|
54707
54737
|
undefined,
|
|
54708
54738
|
topRight: (ySplit &&
|
|
54709
|
-
new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width:
|
|
54739
|
+
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 })) ||
|
|
54710
54740
|
undefined,
|
|
54711
54741
|
bottomLeft: (xSplit &&
|
|
54712
|
-
new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height:
|
|
54742
|
+
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 })) ||
|
|
54713
54743
|
undefined,
|
|
54714
54744
|
bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
|
|
54715
|
-
width:
|
|
54716
|
-
height:
|
|
54745
|
+
width: unfrozenWidth,
|
|
54746
|
+
height: unfrozenHeight,
|
|
54717
54747
|
}, { canScrollHorizontally, canScrollVertically }, {
|
|
54718
54748
|
x: canScrollHorizontally ? previousOffset.x : 0,
|
|
54719
54749
|
y: canScrollVertically ? previousOffset.y : 0,
|
|
@@ -54725,7 +54755,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54725
54755
|
* Adjust the viewport such that the anchor position is visible
|
|
54726
54756
|
*/
|
|
54727
54757
|
refreshViewport(sheetId, anchorPosition) {
|
|
54728
|
-
|
|
54758
|
+
this.getSubViewports(sheetId).forEach((viewport) => {
|
|
54729
54759
|
viewport.adjustViewportZone();
|
|
54730
54760
|
viewport.adjustPosition(anchorPosition);
|
|
54731
54761
|
});
|
|
@@ -54790,12 +54820,26 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
54790
54820
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
54791
54821
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
54792
54822
|
}
|
|
54793
|
-
|
|
54794
|
-
|
|
54795
|
-
|
|
54796
|
-
|
|
54797
|
-
|
|
54798
|
-
|
|
54823
|
+
mapViewportsToRect(sheetId, rectCallBack) {
|
|
54824
|
+
let x = Infinity;
|
|
54825
|
+
let y = Infinity;
|
|
54826
|
+
let width = 0;
|
|
54827
|
+
let height = 0;
|
|
54828
|
+
let hasViewports = false;
|
|
54829
|
+
for (const viewport of this.getSubViewports(sheetId)) {
|
|
54830
|
+
const rect = rectCallBack(viewport);
|
|
54831
|
+
if (rect) {
|
|
54832
|
+
hasViewports = true;
|
|
54833
|
+
x = Math.min(x, rect.x);
|
|
54834
|
+
y = Math.min(y, rect.y);
|
|
54835
|
+
width = Math.max(width, rect.x + rect.width);
|
|
54836
|
+
height = Math.max(height, rect.y + rect.height);
|
|
54837
|
+
}
|
|
54838
|
+
}
|
|
54839
|
+
if (!hasViewports) {
|
|
54840
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
54841
|
+
}
|
|
54842
|
+
return { x, y, width: width - x, height: height - y };
|
|
54799
54843
|
}
|
|
54800
54844
|
}
|
|
54801
54845
|
|
|
@@ -61134,6 +61178,6 @@ exports.tokenColors = tokenColors;
|
|
|
61134
61178
|
exports.tokenize = tokenize;
|
|
61135
61179
|
|
|
61136
61180
|
|
|
61137
|
-
__info__.version = "17.2.
|
|
61138
|
-
__info__.date = "2025-
|
|
61139
|
-
__info__.hash = "
|
|
61181
|
+
__info__.version = "17.2.36";
|
|
61182
|
+
__info__.date = "2025-02-10T08:59:25.719Z";
|
|
61183
|
+
__info__.hash = "5a942bd";
|